A类中的函数指针到B类的成员函数

时间:2013-03-11 18:48:53

标签: c++ pointers function-pointers

我现在正在为此寻找一个解决方案。没有发现任何相关问题足以令人遗憾地回答所以这是我的问题。 考虑下一个代码:

// dummy class A
class A {
public:
    void aFunction() { // <- this is the function I want to point at
        cout << "aFunction() is called\n";
    }
};

class B {
public:
    template <class Class> // get a function pointer
    void setFunction( void (Class::*func)() ) {
        p_func = func;
    }
    void (*p_func)(); // the function pointer
}

int main() {
    B obj;
    objb.setFunction(&A::aFunction);
    return 0;
}

setFunction() p_func = func;上的编译错误:

  

无法从'void(__ thiscall A :: *)(void)'转换为'void(__ cdecl *)(void)'

我似乎无法以任何方式摆脱它。我知道它与那些不可见的this指针(__thiscall__cdecl)有关,但我不知道如何处理它们。我尝试使成员变量p_func也成为一个类模板(void (Class::*p_func)()),因此它具有相同的结构,但是在一个类中有两个类模板似乎是非法的(为什么?),因此不是正确的解决方案。这次编译器抱怨:

  

不允许使用多个模板参数列表

这个方法(没有模板)完全适用于全局函数(这是我目前使用的解决方法),我看到它在库(sfgui)中的使用,所以它应该是完全可能的。

要了解我为什么要这样做的背景:我正在尝试创建一个按钮。这个按钮应该可以调用我想要的任何功能。现在,我希望它能调用我正在制作的动画类的start()函数。

p.s:我知道这个例子没用,因为我无法运行p_func:该函数不是静态的。我仍然需要添加一个对象指针(setFunction( void (Class::*func)(), Class* )),但这似乎不是问题。我知道typedef使函数指针更具可读性,但不能使用类模板。


修改

经过一些研究后,我认为答案我不需要回答这个问题,而是另一个问题。这一次,我注意到事实上允许多个template <class Class>。但是,它不允许在成员变量上,因为编译器不可能知道他需要使用哪个class这可能是错误的原因

  

不允许使用多个模板参数列表

这是一个奇怪的描述。无论如何,谢谢你的帮助,你确实给了我更好的见解。

2 个答案:

答案 0 :(得分:3)

您无法将指向成员Class::*func的指针转换为普通函数指针。它们有不同的类型。

你应该转过来:

void (*p_func)(); // the function pointer

进入这个:

void (class::*p_func)(); // the function pointer

您还可以使用std::function<void()>并使用boost::bind绑定它。

std::function<void()> fun = boost::bind(class::member_fun, args);

修改

如何将B类设为模板,以便执行此操作:

#include<iostream>

class A {
public:
    void aFunction() { // <- this is the function I want to point at
        std::cout << "aFunction() is called\n";
    }
};

template<class T>
class B {
public:
    void setFunction( void (T::*func)() ) {
        p_func = func;
    }
    void (T::*p_func)(); // the function pointer
    void callfunc()
    {
       (t.*p_func)(); //call pointer to member
    }
   private:
   T t; 
};

int main() {
    B<A> obj;
    obj.setFunction(&A::aFunction);
    return 0;
}

Live Example

答案 1 :(得分:0)

我在寻找一种方法来保存未知类型的对象而不使用已经回答here的模板或无效指针时,我找到了完整的答案。解决方案有点狡猾,因为您必须创建一个允许某些转换的虚拟父级。

我们的想法是创建一个Parent,并且允许指向的每个对象都必须从中继承。这样你可以创建一个指针Parent *obj,它可以容纳多种类型的对象,但当然只有从Parent继承的类。

这同样适用于函数指针。如果将指针定义为void (Parent::*func)()作为成员变量。您可以向用户询问模板函数指针template <class Class> setFunction( void (Class::*f)() ),它可以保存任何类的指针。现在,您需要将函数指针强制转换为所需的类Parentstatic_cast<void(Parent::*)()>(f)。请注意,这仅在Class继承自Parent时才有效。否则你会收到编译错误。

最小工作示例

#include <iostream>
using namespace std;

// dummy class Parent
class Parent {};

// class A
class A : public Parent { // Mind the inheritance!
public:
    A(int n) : num(n) {}

    void print() {  // <- function we want to point to
        cout << "Number: " << num << endl;
    }

    int num;
}

// class B, will hold the 2 pointers
class B {
public:
    B() {}

    template <class Class>  // will save the function and object pointer
    void setFunction( void (Class::*func)(), Class *obj) {
        function = static_cast<void(Parent::*)()>(func);
        object = obj;
    }

    void execFunction() {  // executes the function on the object
        (object->*function)();
    }

    void (Parent::*function)(); // the function pointer
    Parent *object;             // the object pointer
}

int main() {
    A a(5);
    B b;

    b.setFunction(&A::print, &a);
    b.execFunction();

    return 0;
}

我真的不喜欢这个解决方案。一个更好的解决方案是类B可以有一个函数,当需要执行函数时它返回一个bool。这样,您只需在执行所需函数的if函数中放置main语句。

A a(5);
B b;
while (;;) {
    if (b.aTest())
        a.print();
}

B::aTest()声明为

bool B::aTest();

希望这有助于遇到同样问题的任何人。所以这是完全可能的,但在我看来非常狡猾,我不鼓励人们使用第一种方法。