C ++多态性:有什么方法可以找到对象的成员函数的地址?

时间:2018-07-13 15:27:24

标签: c++

如果我有一个纯的虚拟基类,它有多个派生类...

class Base
{
public:
   virtual void method1() = 0;
}

class Derived1 : public Base
{
public:
   void method1() override { ... }
}

class Derived2 : public Base
{
public:
   void method1() override { ... }
}

是否有任何方式可以保存持有未知派生类型的对象的Base*的代码,以确定其持有method1()指针的对象的Base*函数的地址?

我想做的是这样的:

void someOtherFunction(Base * pb)
{
   printf("If I call pb->method1(), it will call a function at %p.\n",
          &(pb->method1));
}

但是我遇到了编译器错误:

  

错误:ISO C ++禁止采用绑定成员函数的地址   形成指向成员函数的指针。

理想情况下,任何解决方案都应避免使用RTTI和dynamic_cast,因为我的嵌入式系统没有启用或允许使用RTTI。

2 个答案:

答案 0 :(得分:0)

您要寻找的是pointer to (virtual) member function。请注意,这样的指针不是函数的地址,而是通常在vtable中的偏移量,因为实际调用的函数取决于对象的实际类型。您甚至无法将此指针转换为void*,该表示形式是实现定义的。 这还意味着您无法找到将以通用方式调用的实际函数的地址

如果您真的需要知道要调用的目标函数,也许最好使用几个单独的函数和一个枚举?

无论如何,如果只希望能够通过指针调用虚拟成员函数,则可以执行以下操作:

void someOtherFunction(Base* pb)
{
    using func_t = void(Base::*)(); // Type of a pointer to member function of
                                    // signature void() and object type Base
    func_t fn = &Base::method1; // Take the address of the function
    (pb->*fn)(); // Call it. Note the extra parenthesis and the operator: ->*
                 // The actual function called depends on the actual type of pb,
                 // it can be Derived1::f() or Derived2::f() in the example code you have
}

答案 1 :(得分:-1)

在不知道自己要完成什么的情况下,很难给出建议。我会遵循以下条件:使用lambda。

例如,捕获和不捕获:

Base* b = ...;

// non capturing, convertible to function pointer
auto lambda1 = [](Base*) { b->method1() }
auto fptr = static_cast<void(*)(Base*)>(lambda1);

lambda1(b);
fptr(b);

// capturing
auto lambda2 = [b]{ b->method1() };

lambda2();

// can be stored in a std::function if you need them in a collection
std::function func = lambda2;