如果我有一个纯的虚拟基类,它有多个派生类...
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。
答案 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;