2011-01-28 62 views
21

Tôi muốn khai báo định nghĩa kiểu cho chữ ký hàm thành viên. typedefs chức năng toàn cầu giống như thế này:Cú pháp chữ ký hàm thành viên C++ typedef

typedef int (function_signature)(int, int); 
typedef int (*function_pointer) (int, int); 

Nhưng tôi không thể để điều tương tự cho một hàm thành viên:

typedef int (foo::memberf_signature)(int, int); // memberf_pointer is not a member of foo 
typedef int (foo::*memberf_pointer)(int, int); 

Nghe có vẻ hợp lý với tôi, bởi vì "foo ::" ist sự cú pháp để truy cập một thành viên trong lớp foo. Tôi chỉ có thể gõ chữ ký như thế nào?

+0

Chỉ cần ra khỏi tò mò, tại sao bạn đang cố gắng làm điều này? –

+4

Tôi đang bối rối, là 'typedef' cuối cùng không phải những gì bạn muốn? – GManNickG

+0

Điều đó có vẻ không đồng nhất với tôi. Có thể gõ một hàm được khai báo ở phạm vi toàn cục, nhưng không thể gõ một phương thức. Và có, tôi đang phân biệt giữa chữ ký và kiểu con trỏ hàm. – 0xbadf00d

Trả lời

10

đối với câu hỏi về cú pháp con trỏ hàm vụng về, cá nhân tôi sử dụng một cheat-sheet: The Function Pointers Tutorial (downloadable here, nhờ số Vector để chỉ ra).

Chữ ký của hàm thành viên, tuy nhiên, hơi khác so với chữ ký của hàm thông thường, như bạn đã trải nghiệm.

Như bạn có thể biết, hàm thành viên có thông số ẩn, this, loại cần được chỉ định.

typedef int (Foo::*Member)(int, int); 

không cho phép bạn xác định rằng các yếu tố đầu tiên truyền cho hàm sẽ là một Foo* (và do đó phương pháp của bạn thực sự mất 3 lập luận, khi bạn nghĩ về nó, không chỉ là 2.

Tuy nhiên có

Một con trỏ hàm có thể tham chiếu đến một hàm ảo, trong trường hợp đó mọi thứ có thể trở nên khá phức tạp, do đó, kích thước rất của các thay đổi biểu diễn trong bộ nhớ tùy thuộc vào trên loại chức năng. Thật vậy, trên Visual S tudio, kích thước của con trỏ hàm có thể thay đổi từ 1 đến 4 lần kích thước của con trỏ thông thường. Điều này phụ thuộc vào việc chức năng là ảo, đáng chú ý.

Do đó, lớp chức năng đề cập đến là một phần của chữ ký và không có xung quanh công việc.

+0

liên kết của bạn bị hỏng –

+0

@ BЈовић: và nó cũng là một liên kết tốt ... oh well thankfully Tôi biết một bài viết thứ hai;) –

+0

Liên kết làm việc mới với _downloads_ cho [** Hướng dẫn về chức năng **] (http: //www.newty.de/fpt/dload.html) – Vector

1

Lý do không hoạt động với cú pháp hiện tại của bạn là ưu tiên toán tử quy định rằng bạn đang tham chiếu đến hàm có tên foo::memberf_signature, không phải loại nào.

Tôi không biết chắc liệu bạn có thể làm điều này hay không, nhưng tôi không thể tìm ra bất kỳ sự kết hợp nào của parenthese đã tạo ra mã để biên dịch với g ++ 4.2.

+0

Điều gì về chỉ ':: memberf_signature' có thể? – user470379

-3

Về cơ bản, nó không thể hoạt động (ít nhất tôi không biết cách nào sử dụng g ++); Sử dụng trình biên dịch borland C++ sẽ có từ khóa __closure.

Lý do tại sao nó không biên dịch là, kích thước của con trỏ chức năng (trên máy x86) chiếm luôn < < 32 bit >>; nhưng nếu bạn muốn trỏ đến một lớp (giao diện) chữ ký, sizeof phải là 64 bit: 32 bit cho con trỏ này (vì giao diện lớp chỉ trong bộ nhớ một lần) và 32 bit cho hàm thực tế

nhưng từ khóa __closure là một ngôn ngữ bcb 'Hack' không được chuẩn hóa ...

+0

Thực tế là các con trỏ hàm thành viên và các con trỏ hàm có các kích thước khác nhau có vẻ không liên quan đến tôi. Thông thường, 'short' và' double' có kích thước khác nhau, nhưng bạn có thể 'typedef' với cả hai. –

+1

Con trỏ 'this' này thường được chuyển thành tham số ẩn đầu tiên. Tôi đã không nghe nói về bất kỳ trình biên dịch bằng cách sử dụng một con trỏ 64-bit để munge con trỏ này vào con trỏ đến một đối tượng. –

+0

Điều đó hoàn toàn sai. Con trỏ này được lưu trữ trong (ví dụ: MSC) ECX-Register trên máy mục tiêu IA-32. Bất kỳ con trỏ nào luôn là 32 bit trên một hệ thống như vậy. – 0xbadf00d

2

Nó làm việc cho tôi:

#include <iostream> 

class foo 
    { 
public: 
    int g (int x, int y) { return x + y ; } 
    } ; 

typedef int (foo::*memberf_pointer)(int, int); 

int main() 
    { 
    foo f ; 
    memberf_pointer mp = &foo::g ; 
    std::cout << (f.*mp) (5, 8) << std::endl ; 
    } 
+0

Đó là một typedef cho một con trỏ hàm thành viên. Đó là công việc của tôi, nhưng không phải là những gì tôi đang theo;) – 0xbadf00d

+0

OK, bây giờ tôi thấy những gì bạn muốn. Nhưng làm thế nào để bạn có kế hoạch sử dụng typedef này, nếu bạn quản lý để tạo ra nó? – TonyK

3

Bạn có thể yếu tố ra lớp đối tượng trong C++ hiện đại (gửi 11) bằng cách sử dụng 'typedefing' chất của mẫu bí danh. Những gì bạn cần sẽ trông như thế như:

template<typename T> 
using memberf_pointer = int (T::*)(int, int); 

Tuy nhiên, tại thời điểm kê khai, một con trỏ tới hàm thành viên sử dụng cú pháp này sẽ cần phải xác định lớp mục tiêu:

// D is a member function taking (int, int) and returning int 
memberf_pointer<foo> mp = &foo::D; 
Các vấn đề liên quan