2014-06-05 32 views
2

当我试图阐明我的问题时,忍受着我。我想我正在试图了解的东西是这样的:C++编译器如何处理具有多重继承的偏移量?

class Base1 { public: int value { 5 }; }; 
class Base2 { /* fields */ }; 

class Derived1 : public Base1 { ... }; 
class Derived2 : public Base2, public Derived1 { ... }; 

编译器如何解决像这样的代码的内存偏移?

void base1_action(Base1 *instance) { 
    cout << instance->value << endl; 
} 

void change_base(Base2* instance) { 
    base1_action(reinterpret_cast<Base1*>(instance)); 
} 

int main() { 
    Base2* instance = new Derived2; 
    change_base(instance); 
} 

也就是说,如果在main实际的对象实例是Derived2型的,当change_base基地发生变更从Base2Base1,怎么是编译器能够知道如何重新计算的偏移这样当base1_action被调用时,它会得到一个指向Base1的正确偏移的指针?

换句话说,当存在多重继承时,编译器如何计算从一个基类到另一个基类的偏移量(而不是从已知派生类计算基类偏移量的简单问题)?

希望我的问题有点清楚 - 谢谢!

+0

给出的示例代码不会编译。请提供编译的代码。 –

+1

精灵魔法和一个实现定义塔科。 –

+0

已编辑,现在应该编译。 – sircodesalot

回答

5

base1_action(reinterpret_cast<Base1*>(instance));

“如何能够知道如何重新计算偏移量为对象的编译器”

它没有。您正在使用reinterpret_cast,这意味着类似“这里是一种类型的位,现在把它当作是其他类型的位”。这里没有涉及抵消计算。换句话说:这是代码中的一个错误。

如果您要编写static_castdynamic_cast而不是编译器确实需要计算偏移量。既然它知道类型和内存布局的类型,它可以很容易地添加或减去正确的偏移量。如果要隐藏类型,例如在static_cast之前分配指向void *的指针,将无法应用正确的偏移计算。

+0

啊,所以我想要做的事情(侧身演员)真的不可能编译器来确定。是对的吗? – sircodesalot

+0

@sircodesalot我不知道横向投射是什么意思。如果使用正确的类型,编译器会做正确的事情。如果你不这样做,你最有可能得不到正确的行为。 – nwp

+0

换句话说,对于实现两个基地的某种类型,直接从一个基地直接投射到另一个基地 - 这是不允许的? – sircodesalot

0

它认为,GCC/MinGW的会做这种方式:

class Base1 { public: int value { 5 }; } 
class Base2 { /* fields */ } 
class Derived1 : public Base1 { ... } 
class Derived2 : public Base2, public Derived1 { ... } 


Derived2: 
    Base2 fields 
    Derived1: 
     Base1 fields 
     Derived1 fields 
    Derived2 fields 
+0

这不解释OP的问题... – laune

+0

我不知道我还可以添加到我的答案。如果OP知道字段的位置,他应该很清楚如何计算偏移量。 – HolyBlackCat

+0

如果你看看函数签名,我认为它应该更清楚我要问什么。 – sircodesalot