1

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

// 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_funcvoid (Class::*p_func)()这次编译器抱怨:

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

这种方法(没有模板)在全局函数(这是我目前使用的解决方法)上完美地工作,我在库(sfgui)中看到了它的使用,所以它应该是完全可能的。

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

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


编辑

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

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

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

4

2 回答 2

3

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

你应该把这个:

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

进入这个:

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

你也可以使用 astd::function<void()>和 useboost::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;
}

现场示例

于 2013-03-11T18:51:26.730 回答
0

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

这个想法是您创建一个 Parent 并且允许指向的每个对象都必须从它继承。通过这种方式,您可以创建一个指针,Parent *obj它可以容纳多种类型的对象,但当然只有继承自Parent.

这同样适用于函数指针。如果您将指针定义void (Parent::*func)()为成员变量。你可以向用户询问一个模板函数指针template <class Class> setFunction( void (Class::*f)() ),它可以保存任何指向任何类的指针。现在您需要将函数指针转换为所需的类Parent: static_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可以具有一个函数,当需要执行该函数时,它会返回一个布尔值。这样,您可以简单地在执行所需函数if的 -function 中放置一条语句。main

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

在哪里B::aTest()声明为

bool B::aTest();

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

于 2013-03-12T12:34:19.607 回答