2017-06-01 47 views
1

我想從類「調用者」中調用類「A」和「B」的幾種方法。我需要使用函數指針,因爲我想調用不同的方法。如何使用函數指針調用對象的方法?

我的方法被調用,但是當我嘗試從它訪問一個成員變量時,我的程序崩潰('program.exe已停止工作')。

這是怎麼回事?

#include <iostream> 

using namespace std; 


template <class T> 
class Caller 
{ 
    typedef void (T::*myFunc)(int); 
    public: 
     Caller(T* obj, myFunc fp) 
     { 
      f = fp; 
     } 
     void invoke(int foobar) 
     { 
      (o->*f)(foobar); 
     } 
    private: 
     myFunc f; 
     T* o; 
}; 

class A 
{ 
    public: 
     A() : n(0) {} 
     void foo(int bar) 
     { 
      cout << "A::foo called (bar = " << bar << ", n = " << n << ")" << endl; // the crash occurs here, and 'this' equals 0 at this point 
     } 
     void setNum(int num) 
     { 
      n = num; 
     } 
    private: 
     int n; 
}; 

class B 
{ 
    public: 
     B() : n(0) {} 
     void fooo(int bar) 
     { 
      cout << "B::fooo called (bar = " << bar << ", n = " << n << ")" << endl; // same here if I call B::fooo first 
     } 
     void setNum(int num) 
     { 
      n = num; 
     } 
    private: 
     int n; 
}; 

int main() 
{ 
    A myA; 
    B myB; 

    myA.setNum(128); 
    myB.setNum(256); 

    Caller<A> cA(&myA, &A::foo); 
    Caller<B> cB(&myB, &B::fooo); 

    cA.invoke(10); 
    cB.invoke(20); 

    return 0; 
} 

在此先感謝您。

編輯:我使用VS2017,我可以構建我的程序而不會收到任何編譯器錯誤。

回答

1

我的方法被調用,但是當我嘗試從它訪問一個成員變量,我的程序崩潰...

因爲你忘了你的Caller來分配傳遞到obj指針o

template <class T> 
class Caller 
{ 
    typedef void (T::*myFunc)(int); 
public: 
    Caller(T* obj, myFunc fp) 
    { 
     o = obj; // << == you need this! 
     f = fp; 
    } 
    void invoke(int foobar) 
    { 
     (o->*f)(foobar); 
    } 
private: 
    myFunc f; 
    T* o; 
}; 

而且,一般而言,最好使用member initializer lists

Caller::Caller(T* obj, myFunc fp) : o(obj), f(fp) 
{ 
} 
+0

非常感謝你帕維爾!現在它就像一個魅力!我不敢相信我犯了這樣一個愚蠢的錯誤......並感謝您的建議。我也想知道我是否可以存儲和調用我的方法?我的意思是沒有它的對象 – winapiwrapper

+1

你不能調用非靜態方法沒有任何對象,它根本沒有意義。如果您將其設爲靜態,那麼您可以像調用其他任何非成員函數一樣調用它。 – Pavel

+0

好吧,我現在明白了。非常感謝帕維爾。 – winapiwrapper

相關問題