向下指向成员函数的指针。这是合法用法吗?

时间:2019-06-10 18:05:56

标签: c++ inheritance language-lawyer member-function-pointers

我将指向成员函数的指针列表存储在数组中。我想索引数组并执行适当的功能。将有许多列出来自不同类的函数的数组(所有类均来自Base),因此在编译时不知道该类。

我有该方案,但我对必须在一个地方使用空指针并不完全满意,但我似乎无法避免。

我是否根据C ++ 11标准在Base和Derived成员函数指针之间进行强制转换(正在与g ++一起使用)。我将感谢语言律师的建议!

下面是我的代码的精简但可运行的版本。

#include <iostream>

using std::cout;

//*************************************

class Base {
public:

  typedef int (Base::*BaseThunk)();

  virtual int execute(BaseThunk x) {return 0;}

};

//*************************************

class Derived : public Base {
public:

  typedef int (Derived::*DerivedThunk)();

  int execute(BaseThunk step) {
    return (this->*step)(); //Is this OK ? step is really a DerivedThunk.
  }

  int f1() { cout<<"1\n";return 1;}
  int f2() { cout<<"2\n";return 2;}
  int f3() { cout<<"3\n";return 3;}

  static DerivedThunk steps[];
};

//Here is an array of pointers to member functions of the Derived class.
Derived::DerivedThunk Derived::steps[] = {&Derived::f1, &Derived::f2, &Derived::f3};

//*************************************

class Intermediate : public Base {
public:

  void f(void *x) { //I am worried about using void pointer here !

    BaseThunk *seq = reinterpret_cast<BaseThunk *>(x);

    Derived d;
    d.execute(seq[2]);
  }

};

//*************************************

int main() {
  Intermediate b;

  b.f(&Derived::steps);
}

1 个答案:

答案 0 :(得分:1)

您对void*的担忧是有充分根据的:这是未定义的行为,因为(在Intermediate::f中)您正在对指针执行算术运算,并对其进行通读与数组的类型不匹配。

好消息是,有一个简单的解决方法:由于数组的目的是仅给定Base&BaseThunk来调用派生类函数,因此您可以商店,该类型:

Base::BaseThunk Derived::steps[]=
  {static_cast<BaseThunk>(&Derived::f1),
   …};

static_cast有点冗长,但只要您使用具有类型为或源自{{1的对象的}}。您甚至不必先获得BaseThunk

Derived