将指针从派生类转换为基类的最佳方法

Posted

技术标签:

【中文标题】将指针从派生类转换为基类的最佳方法【英文标题】:Best approach for casting pointer to method from derived to base class 【发布时间】:2019-05-23 15:59:13 【问题描述】:

我们有一个旨在通用的基类 ByteCode。 ByteCode 的子级应该编写如下形式的方法:

void m();

ByteCode 类应该有一个方法定义:

typedef void (ByteCode::*Method)();

为了执行字节码,我们有:

void exec() 
  while (true) 
    uint16_t opcode = getOpcode();
    Method m = opcodes[opcode];
    this->*m();
  

在一堂课上这样做是没有问题的。但是我们在基类中有泛型代码,而派生有数组:

class MyByteCodeEngine : public ByteCode 
private:
  static Method opcodes[65536];

  void m1() 
  void m2() 
  void m3() 
;

Method MyByteCodeEngine ::opcodes[65536] = 
  MyByteCodeEngine::m1,
  MyByteCodeEngine::m2,
  MyByteCodeEngine::m3

问题是这些方法不是基类,它们是派生的。但是我们唯一拥有的实例是派生的,我们不想招致虚拟的开销,我们只想强制转换并使其工作,但编译器正在捕捉每一个技巧。如果它只是信任我们:

Method MyByteCodeEngine ::opcodes[65536] = 
  (Method)MyByteCodeEngine::m1,
  (Method)MyByteCodeEngine::m2,
  (Method)MyByteCodeEngine::m3

我们可以通过消除 ByteCode 类来解决这个问题,但这会迫使我们在任何有字节码解释器时重复代码。关于如何欺骗 C++ 干净地接受这一点的任何建议?

【问题讨论】:

我会使用 std::vector<std::function<void ()>> 并使用捕获 this 的 lambdas 来初始化它们。 【参考方案1】:

您可以使用Curiously recurring template pattern 以便基类知道成员函数的类型。

template<class T>
struct ByteCode 
  typedef void (T::* Method)();

  void exec() 
    while (true) 
      uint16_t opcode = getOpcode();
      Method m = T::opcodes[opcode];
      static_cast<T*>(this)->*m();
    
  
;

class MyByteCodeEngine : public ByteCode<MyByteCodeEngine > 
  private:
    static Method opcodes[65536];

    void m1() 
    void m2() 
    void m3() 
;

MyByteCodeEngine::Method MyByteCodeEngine ::opcodes[65536] = 
  &MyByteCodeEngine::m1,
  &MyByteCodeEngine::m2,
  &MyByteCodeEngine::m3

【讨论】:

我也想过。我相信将 CRTP 与我在 OP 的评论中的提案结合使用将是最好的和最安全的方法。 当然。这就是 CRTP 的用途。 @πάνταῥεῖ 不知道,std::function 可能有点沉重。虽然我相信常见的实现对简单的函数指针有优化——不确定这是否也适用于指向成员的指针。向量是另一个不必要的动态分配(虽然我会考虑std::array @Light 好吧,开销当然是一个很好的反对理由。 也想知道是否真的需要继承。只是有一个ByteCodeExecuter&lt;T&gt; 吗?但它可能是真正的 *ByteCodeEngine 类型具有其他需要继承的功能和东西

以上是关于将指针从派生类转换为基类的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

Part7 继承与派生 7.3基类与派生类类型转换

C#通过反射将派生类转换为基类异常

向上强制转换和向下强制转换

类型兼容规则

将派生类转换为基类

C++:派生模板类和基类之间的向下转换和向上转换?