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

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

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

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

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

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

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

虚拟继承引入了一个额外的间接层来解决这种歧义.不是在编译时确定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();

转载注明原文:c – 多个虚拟继承是否涉及后期绑定,如虚拟函数的继承? - 代码日志