2011-06-07 65 views
16

theo MSDN cú pháp typedef là:typedef cú pháp với con trỏ hàm thành viên

typedef kiểu khai đồng nghĩa;

Rất dễ dàng:

typedef int MY_INT; 

Nhưng làm thế nào heck nào typedefs viên-chức năng-con trỏ tuân thủ quy tắc này?

typedef int (MyClass::*MyTypedef)(int); 

100% nhầm lẫn - từ đồng nghĩa (MyTypedef) đang ở giữa?

Có thể ai đó vui lòng giải thích những bước hợp lý nào để nhận được từ định dạng cú pháp rất dễ hiểu của MSDN tới cú pháp đảo ngược/ngẫu nhiên/trước/cuối/hỗn hợp của aboves typedef?

* chỉnh sửa nhờ cho tất cả các câu trả lời nhanh (và đẹp của bài viết của tôi) :)

+8

Nó không - MSDN là sai. –

+1

Vâng, MSDN là sai. 'int typedef MY_INT' có cùng ý nghĩa! – ybungalobill

Trả lời

28

từ đồng nghĩa (MyTypedef) là ở giữa ??

Không ở giữa. Chỉ cần quên thành viên chức năng trong một thời gian, xem làm thế nào một con trỏ hàm được định nghĩa:

int (*FuncPtr)(int); 

Và đây là cách bạn sẽ typedef nó:

typedef int (*FuncPtr)(int); 

đơn giản! Điểm khác biệt duy nhất là, trong typedef FuncPtr trở thành một loại , trong khi khai báo con trỏ, FuncPtr là một biến số .

Tương tự,

int (MyClass::*MyTypedef)(int); //MyTypedef is a variable 

Và typedef như:

typedef int (MyClass::*MyTypedef)(int); //MyTypedef is a type! 
+1

Tôi nghĩ rằng vị trí của '*' là một phần khó hiểu, nên có thể đáng nhắc nhở rằng tiền tố "khai báo" là đúng liên kết, vì vậy khai báo được đánh giá là "MyTypedef là một' con trỏ tới '' MyClass's '' function taking int' "vv – davka

9

Làm thế nào để bạn định nghĩa một con trỏ tới hàm thành viên? Như thế này:

int (A::*variableName)(int); 

Để làm cho nó một typedef, chỉ cần thêm một typedef:

typedef int (A::*typedefName)(int); 
3

Nguyên tắc khai trong C++ là họ mimick việc sử dụng. Nếu bạn muốn sử dụng một con trỏ tới hàm thành viên PMF, bạn sẽ viết:

(myVar.*pmf)(arg); 

như vậy để xác định một typedef cho nó, bạn viết:

typedef int (MyClass::*pmf)(int); 

thêm các kiểu trả về trong đầu, thay thế biến theo loại và đối số theo loại của chúng.

+0

+1 đó là cách tôi hiểu chúng! Rất tiếc, không phải lúc nào cũng được áp dụng (ví dụ: tham chiếu). – ybungalobill

+0

Có cách nào để sử dụng "(myVar. * Pmf) (arg);" mà không có đối tượng "myVar"? – pBlack

1

Tôi đã từng đọc một lời giải thích tốt đẹp (nhưng đó là từ Expect C Programming vì vậy tôi YMMV):

Trong thực tế, một typedef có giống hệt nhau định dạng như một khai báo biến, chỉ với từ khóa phụ này đấm bạn tắt.

Vì typedef trông giống hệt như khai báo biến , nó được đọc chính xác như một. Thay vì khai nói "tên này ám chỉ cho một biến của các loại nêu," từ khóa typedef không tạo ra một biến , nhưng gây ra việc kê khai để nói "Tên này là một từ đồng nghĩa với tuyên bố kiểu."

Vì vậy, bạn đã có nó. Hãy tưởng tượng bạn đang khai báo một biến, dính typedef trước nó và thì đấy, bạn có một kiểu mới. MSDN giải thích là một túi hỗn hợp: Tôi đã đọc những người thực sự thần và những người hết sức xấu.

1

Trang bạn đang đề cập có thể là "typedef Specifier". Cú pháp "typedef type-declaration synonim;" đơn giản chỉ là một trong nhiều cách để sử dụng typedef. Có (có lẽ) không có cách đơn giản và ngắn gọn nào để mô tả cách typedef có thể được sử dụng. Đó là những gì trang "MSN Typedef Declarations" dành cho.

Bạn sẽ nhận thấy về vấn đề này một cái gì đó trang như:

declaration: 
    declaration-specifiers init-declarator-list opt ; 
declaration-specifiers: 
    storage-class-specifier declaration-specifiers opt 
    type-specifier declaration-specifiers opt 
    type-qualifier declaration-specifiers opt 
storage-class-specifier: 
    typedef 

Thông tin chi tiết như những gì tuyên bố-specifiers và init-declarator-list có thể được tìm thấy here.

Đây là một cách nghiêm ngặt để hiểu tất cả các tập quán có thể có cho "typedef".

Trang này cơ bản nói gì là "typedef" có thể được sử dụng trước khi khai báo hợp lệ nhất.

0

Nó sẽ được dễ dàng hơn để hiểu khi bạn bắt đầu nghĩ như thế này:

Bất cứ khi nào bạn thấy một chức năng như thế này:

TYPE foo(int arg1, int arg2); 

Bạn nói rằng các loại foo là TYPE. Vì vậy, loại

int get_next_prime(); 

là int.

Bạn có thể thấy rằng khi bạn vượt qua một con trỏ hàm như một tham số để một hàm:

void register_callback(void (*ptr)(int)); 

Trong trường hợp này, bạn đang đi qua một hàm kiểu void như một cuộc tranh cãi.

Bây giờ, khi bạn nhìn thấy một cái gì đó như thế:

typedef int (A::*typedefName)(int); 

bạn chỉ nói rằng các biến (A :: * typedefName) (int) (đây là chỉ có một điều, không phải là hai, vì nó là một khai báo con trỏ hàm) thực sự là kiểu int.Từ đó trở đi, trình biên dịch sẽ giải thích A :: * typedefName như một hàm của kiểu int, nghĩa là, nó trả về giá trị int.

Hy vọng điều đó khiến bạn khó hiểu hơn.

+0

Xin lỗi để hỏi, nhưng lời giải thích ở trên có chính xác không? Tôi chỉ thấy khó để nói rằng loại get_next_prime là int. –

4

Tôi biết bạn đã có câu trả lời nhưng muốn chia sẻ câu trả lời này - tiện dụng: http://www.cdecl.org. Đó là một tờ khai C/C++ < -> Biên dịch viên tiếng Anh. Chỉ cần gõ vào

khai báo x là con trỏ tới thành viên của lớp Một chức năng (int) trở về char

và bạn nhận char (A::*x)(int). Hoặc chơi xung quanh với tuyên bố và xem nếu bạn có được những gì bạn muốn.

9

Nó đáng chú ý là, như C++ 11, bạn có thể viết biểu thức này như một dễ đọc hơn using tuyên bố:

using MyTypedef = int (MyClass::*)(int); 
1

Cú pháp của sử dụng con trỏ hàm thành viên phải (giả sử a là một thể hiện của lớp A):

  • khi khai báo, sử dụng " A :: "làm tiền tố
  • khi sử dụng, sử dụng" a ". dưới dạng tiền tố

Dưới đây là ví dụ về đồ chơi. Bạn có thể chơi với nó.

#include <stdio.h> 
#include <stdlib.h> 
class A; 
typedef int (A::*F)(double); 

class A { 
public: 
    int funcDouble(double x) { return (int)(x * 2.0); } 
    int funcTriple(double x) { return (int)(x * 3.0); } 

    void set(int a) { 
    if (a == 2) { 
     this->f_ = &A::funcDouble; 
    } else if (a == 3) { 
     this->f_ = &A::funcTriple; 
    } else { 
     this->f_ = NULL; 
    } 
    } 

public: 
    F f_; 
}; 
int main(int argc, char *argv[]) { 
    A a; 
    a.set(2); 
    F f = &A::funcDouble; 
    printf("double of 1 = %d\n", (a.*f)(1)); 

    // Below is equivalent to: 
    // F f2 = a.f_; 
    // printf("double of 1 = %d\n", (a.*f2)(1)); 
    printf("double of 1 = %d\n", (a.*(a.f_))(1)); 

    a.set(3); 
    printf("triple of 1 = %d\n", (a.*(a.f_))(1)); 

    return 0; 
} 
Các vấn đề liên quan