将指针从派生类转换为基类的最佳方法
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<T>
吗?但它可能是真正的 *ByteCodeEngine
类型具有其他需要继承的功能和东西以上是关于将指针从派生类转换为基类的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章