2009-06-13 53 views
38
class Foo { 
public: 
    Foo() { do_something = &Foo::func_x; } 

    int (Foo::*do_something)(int); // function pointer to class member function 

    void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; } 

private: 
    int func_x(int m) { return m *= 5; } 
    int func_y(int n) { return n *= 6; } 
}; 

int 
main() 
{ 
    Foo f; 
    f.setFunc(false); 
    return (f.*do_something)(5); // <- Not ok. Compile error. 
} 

Làm cách nào để làm việc này?Con trỏ hàm C++ (thành viên nhóm) cho hàm thành viên không tĩnh

+1

Không phải là các hàm tĩnh 'func_x' và' func_y' mặc dù chúng không được đánh dấu như vậy? –

Trả lời

31

Điểm mấu bạn muốn là

return (f.*f.do_something)(5); 

(Đó là biên dịch - Tôi đã thử nó)

"*f.do_something" đề cập đến con trỏ bản thân --- "f" cho chúng ta biết nơi nhận giá trị do_something từ. Nhưng chúng ta vẫn cần đưa ra một đối tượng sẽ là con trỏ này khi chúng ta gọi hàm. Đó là lý do tại sao chúng tôi cần tiền tố "f.".

+8

Về mặt kỹ thuật, "f.do_something" trả về con trỏ và toán tử ". *" Gọi hàm con trỏ tới thành viên trên một lớp. –

+0

Vì vậy, tôi giả sử 'return (f. * Foo :: do_something) (5)' cũng nên hoạt động. – ThomasMcLeod

+1

@ThomasMcLeod Nó không. –

0

Thử (f. * Do_something) (5);

35
class A{ 
    public: 
     typedef int (A::*method)(); 

     method p; 
     A(){ 
      p = &A::foo; 
      (this->*p)(); // <- trick 1, inner call 
     } 

     int foo(){ 
      printf("foo\n"); 
      return 0; 
     } 
    }; 

    void main() 
    { 
     A a; 
     (a.*a.p)(); // <- trick 2, outer call 
    } 
+3

+1 cho hai thủ thuật –

+0

Tudok, sau khi thông qua bài viết của bạn lần thứ hai tôi nhận ra rằng bạn đã đưa ra câu trả lời đúng (lừa 2). Cảm ơn. – Girish

+0

Mã của bạn không hoạt động. Tôi sao chép/dán và thử biên dịch. test_function_pointer_2.C: Trong hàm tạo 'A :: A()': test_function_pointer_2.C: 7: error: đối số của kiểu 'int (A ::)()' không khớp 'int (A :: *)() ' – user180574

-4

Tôi nghĩ việc gọi một thành viên không tĩnh của lớp cũng có thể được thực hiện bằng cách sử dụng hàm thành viên tĩnh.

+1

Điều này là không thể. "Khi sửa đổi một thành viên dữ liệu trong một khai báo lớp, từ khóa tĩnh xác định rằng một bản sao của thành viên được chia sẻ bởi tất cả các cá thể của lớp. Khi sửa đổi một hàm thành viên trong khai báo lớp, ** chỉ các thành viên tĩnh **. " Xem [MSDN reference] (http://msdn.microsoft.com/en-us/library/s1sb61xd (v = vs.80) .aspx) – ForceMagic

+0

tốt, bạn có thể giữ một danh sách tất cả các trường hợp máng nhà xây dựng và sau đó gọi nó cho tất cả các trường hợp, nhưng tôi đoán đó là phần nào của một ý tưởng Whack: p –

3
class A { 
    int var; 
    int var2; 
public: 
    void setVar(int v); 
    int getVar(); 
    void setVar2(int v); 
    int getVar2(); 
    typedef int (A::*_fVar)(); 
    _fVar fvar; 
    void setFvar(_fVar afvar) { fvar = afvar; } 
    void insideCall() { (this->*fvar)(); } 
}; 

void A::setVar(int v) 
{ 
    var = v; 
} 

int A::getVar() 
{ 
    std::cout << "A::getVar() is called. var = " << var << std::endl; 
    return var; 
} 

void A::setVar2(int v2) 
{ 
    var2 = v2; 
} 

int A::getVar2() 
{ 
    std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl; 
    return var2; 
} 

int main() 
{ 
    A a; 
    a.setVar(3); 
    a.setVar2(5); 

// a.fvar = &A::getVar; 
    a.setFvar(&A::getVar); 
    (a.*a.fvar)(); 

    a.setFvar(&A::getVar2); 
    (a.*a.fvar)(); 

    a.setFvar(&A::getVar); 
    a.insideCall(); 

    a.setFvar(&A::getVar2); 
    a.insideCall(); 

    return 0; 
} 

Tôi đã mở rộng câu trả lời của Nick Dandoulakis. Cảm ơn bạn.

Tôi đã thêm một hàm đặt con trỏ hàm thành viên từ bên ngoài lớp. Tôi đã thêm một hàm khác có thể được gọi từ bên ngoài để hiển thị cuộc gọi bên trong của con trỏ hàm thành viên.

+0

Thay vì chỉ đăng một khối mã, xin vui lòng * giải thích * tại sao mã này giải quyết vấn đề đặt ra. Nếu không có một lời giải thích, đây không phải là một câu trả lời. –

+0

@MartijnPieters Tôi viết rằng nó được mở rộng từ câu trả lời của Nick Dandoulakis. Nó được giải thích trong đó. Tôi mới trong stackoverflow có lẽ tôi cần phải làm theo một cách khác nhau. –

+0

Vâng, bạn có thể giải thích những gì bạn đã thay đổi, ví dụ, và tại sao. –

0
#include<iostream> 
using namespace std; 

class A { 

public: 
    void hello() 
    { 
     cout << "hello" << endl; 
    }; 

    int x = 0; 

}; 


void main(void) 
{ 

    //pointer 
    A * a = new A; 
    void(A::*pfun)() = &A::hello; 
    int A::*v1 = &A::x; 

    (a->*pfun)(); 
    a->*v1 = 100; 
    cout << a->*v1 << endl << endl; 

    //----------------------------- 
    A b; 
    void(A::*fun)() = &A::hello; 
    int A::*v2 = &A::x; 

    (b.*fun)(); 
    b.*v2 = 200; 
    cout << b.*v2 << endl; 

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