2017-06-01 120 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