繁体   English   中英

多个虚拟继承是否涉及后期绑定,如虚函数的继承?

[英]Does multiple virtual inheritance involve late binding like inheritance of virtual functions?

与继承虚拟功能不同,解析虚拟继承似乎是枯燥无味的,但也许我只是没有创造力(狡猾?)。

虚拟继承是否与虚函数的继承有关? 具体来说,虚拟继承是否会引发后期绑定? 我看不出任何理由。 由于关键字过载,我只是怀疑。

我意识到标准没有指定虚拟继承的实现。 我对大多数非假想的机器都感兴趣,但不完美。

正如虚函数涉及这些成员函数的后期绑定一样,我想你可以说虚拟继承涉及继承数据成员的后期绑定。 每个子类的内存布局可能完全不同,因此如果没有运行时类型信息,则无法解析类似于baseClassInstance->dataMember的表达式。 因此, virtual两种使用都需要使用“vtable”来进行特定于类的查找。

请参阅Edsko de Vries的“多重和虚拟继承的内存布局”,了解GNU编译器集群(gcc)如何实现虚拟继承,包括对象布局,后果等。据我所知,其他编译器在关键点上是相似的。

虚拟继承并非没有运行时成本,但是这种成本的原因不是增加灵活性,而是解决模糊性问题。

例如,一个多继承层次结构,其中类C通过不同的基类继承两次A类。 对类型C的对象的非静态方法A::foo调用现在是不明确的(无论该调用是否为虚拟)。 问题是传递给成员函数的隐式this指针。 通常,内存中每个子类的位置由继承层次结构唯一确定,但在这种情况下,由于AC包含两次,编译器必须决定如何调整成员函数调用的this指针 - 它不能做就它自己而言,它会要求你做出决定。

这个决定更复杂,因为我们不仅可以通过C调用A::foo ,还可以通过C的基类调用。 这造成了一个两难境地:根据我们用来调用的基类,编译器会以不同的方式调整this指针,将我们重定向到内存中A不同位置,具体取决于我们用于调用的指针类型。 事实上,对于每个C实例, A在内存中有两个不同的A实例。

class A {
public:
    void foo();
    [...]
};
class B1 : public A {};
class B2 : public A {};
class C : public B1, public B2 {};

C c;
B1* b1 = &c;
B2* b2 = &c;

//assume foo() changes some internal state of A
b1->foo();
//the state change of the previous line is not visible
//to the next call - they operate on distinct instances of A
b2->foo();

virtual继承引入了一个额外的间接层来解决这种歧义。 不是在编译时确定A相对于其子类的位置,而是执行运行时查找。 这允许编译器传递相同的内存位置调用A::foo ,无论通过哪个派生类进行调用。 对于C每个实例,我们现在在内存中只有一个A实例。

class B1 : virtual public A {};
class B2 : virtual public A {};
[...]

C c;
B1* b1 = &c;
B2* b2 = &c;

//both calls will now operate on the same instance of A
//state changes performed by the one will be observed by the other
b1->foo();
b2->foo();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM