我想知道是否可以在编译时计算基类偏移量。当然,在运行时很容易做到这一点,因为可以利用static_cast的功能,而偏移量只是指向派生类的指针的基指针之间的差异。
我第一次尝试在编译时获取它,结果如下所示:
struct InterfaceRoot {}; struct IInterface1 : InterfaceRoot { virtual void MethodI1() = 0; }; struct IInterface2 : InterfaceRoot { virtual void MethodI2() = 0; }; class CClass : public IInterface1,public IInterface2 { virtual void MethodI1() override { /* do something */ } virtual void MethodI2() override { /* do something */ } }; int main() { CClass instance; constexpr int offsetI1 = 0; //first base class has no offset constexpr int offsetI2 = sizeof(IInterface1); //check pointer values against static_cast IInterface1* pI1 = reinterpret_cast<IInterface1*>(reinterpret_cast<char*>(&instance) + offsetI1); IInterface2* pI2 = reinterpret_cast<IInterface2*>(reinterpret_cast<char*>(&instance) + offsetI2); IInterface1* pI1_static_cast = static_cast<IInterface1*>(&instance); IInterface2* pI2_static_cast = static_cast<IInterface2*>(&instance); return 0; }
这里,pI1和pI1_static_cast与预期相同。然而,pI2和pI2_static_cast并不相等!?
我可以通过向InterfaceRoot添加一个虚函数或将其全部省略来修复此问题。发生这种情况的原因是什么?
如果我这样设置继承树,它将使用前面提到的方法:
struct InterfaceRoot { virtual ~InterfaceRoot() {} }; struct IInterface1 : InterfaceRoot { virtual void MethodI1() = 0; }; struct IInterface2 : InterfaceRoot { virtual void MethodI2() = 0; }; class CClass : public IInterface1,public IInterface2 { virtual void MethodI1() override { /* do something */ } virtual void MethodI2() override { /* do something */ } };
有人知道这是为什么吗?顺便说一句,我正在使用Visual Studio 2017。有没有其他方法可以在编译时实现我的目标,或者我最好在运行时计算ofset并具有较小的运行时开销?