【问题标题】:Member function pointer to unspecified class type - is it possible?指向未指定类类型的成员函数指针 - 可能吗?
【发布时间】:2012-01-17 16:58:02
【问题描述】:

是否可以声明一个函数指针(非 C++ 11)可以指向任何类的成员函数(阅读:不是特定的类)?

例如,如果我有 A、B 和 C 类。C 中声明了一个函数指针,我想在指向 B 的成员函数之一和 A 的成员函数之一之间切换该指针。 C++ 允许这样做吗?

【问题讨论】:

  • 函数指针根本不能指向非静态成员函数,您只能将指针指向非静态成员函数,并且它们具有特定于成员类和成员的类型类型。

标签: c++ function-pointers member-function-pointers c++03


【解决方案1】:

是的,你可以,但你必须删除一些类型安全并跟踪 this 指针以及成员函数。

您可以在http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates 中看到一个用例。基本思路是将对象指针存储为void指针,通过静态方法重定向函数调用。

#include <iostream>
using namespace std;

struct A { void foo() { cout << "A::foo\n"; } };
struct B { void foo() { cout << "B::foo\n"; } };

class C
{
public:
    C() : object_ptr(0), stub_ptr(0) {}

    template <class T, void (T::*TMethod)()>
    static C from_method(T* object_ptr)
    {
        C d;
        d.object_ptr = object_ptr;
        d.stub_ptr = &method_stub<T, TMethod>;
        return d;
    }

    void operator()() const
    {
        return (*stub_ptr)(object_ptr);
    }

private:
    typedef void (*stub_type)(void* object_ptr);

    void* object_ptr;
    stub_type stub_ptr;

    template <class T, void (T::*TMethod)()>
    static void method_stub(void* object_ptr)
    {
        T* p = static_cast<T*>(object_ptr);
        return (p->*TMethod)();
    }
};

int main() 
{
    A a;
    B b;

    C c = C::from_method<A, &A::foo>(&a);

    c();

    c = C::from_method<B, &B::foo>(&b);

    c();

    return 0;
}

上面的代码应该打印出来

A::foo
B::foo

此解决方案比使用std::function 更快,因为它不需要为数据分配堆存储空间,但这只能用于引用成员函数(与声称拥有任何可调用对象的std::function 不同)。

【讨论】:

    【解决方案2】:

    boost::function 可以与boost::bind 一起做到这一点:

    #incluce <boost/function.hpp>
    #include <boost/bind.hpp>
    
    struct A{ void f(); };
    struct B{ void g(); };
    struct C{
      boost::function<void()> _func;
    };
    
    int main(){
      A a; B b; C c;
      c.func = boost::bind(&A::f, &a);
      c.func();
      c.func = boost::bind(&B::g, &b);
      c.func();
    }
    

    【讨论】:

    • 使用类型擦除和std::function 或boost::function 之类的抽象层基本上可以满足发帖人的需求。
    【解决方案3】:

    这是不可能的。当你声明一个类的成员函数时,这个函数有一个隐含的this参数,所以即使你写了void A::func(int i),这个函数实际上也有这个签名:

    void func(A *const this, int i)
    

    您将需要像 Boost.Function 和 Boost.Bind 这样的东西一起使用来完成您想要实现的目标:

    boost::function<void (int)> func;
    A* a = new A;
    func = boost::bind(&A::func, a, _1);
    

    【讨论】:

      【解决方案4】:

      不,但你可以让 A 和 B 有一个共同的基类 X,然后你可以对 A 和 B 使用 T (X::*)(U...)(假设 T 和 U 相同)。

      或者你可以简单地使用boost::variant。

      【讨论】:

        【解决方案5】:

        不,你不能。

        如果可以,那将毫无意义。想象一下,你可以有一个 A 类型的对象,并调用一个指向 B 类型的成员函数的成员函数指针。突然在 B 的成员函数中你会有一个 this 指针,指向地址属于 A 对象,但类型为 B*。

        这取决于您要解决的真正问题是什么(也许您应该问过这个问题),但是您可以尝试让所有类都有一个公共的基本函数(可能是虚拟的)并使用指向它们的指针,但除非你提供给我们更多细节,我们只能猜测。

        另一个更广泛的替代方法是使用 boost::function 对象,这些对象已经与您要调用成员函数的对象绑定。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-27
          • 2013-06-06
          • 2012-08-20
          • 1970-01-01
          • 2015-11-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多