有以下代码:

#include <iostream>

class Base
{
public:
    Base() {
        std::cout << "Base: " << this << std::endl;
    }
    int x;
    int y;
    int z;
};

class Derived : Base
{
public:
    Derived() {
        std::cout << "Derived: " << this << std::endl;
    }

    void fun(){}
};

int main() {
   Derived d;
   return 0;
}

输出:
Base: 0xbfdb81d4
Derived: 0xbfdb81d4

但是,当在派生类中将功能“fun”更改为虚拟时:
virtual void fun(){} // changed in Derived

然后,“this”的地址在两个构造函数中都不相同:
Base: 0xbf93d6a4
Derived: 0xbf93d6a0

另一件事是,如果Base类是多态的,例如我在其中添加了其他虚函数:
virtual void funOther(){} // added to Base

然后两个“this”的地址再次匹配:
Base: 0xbfcceda0
Derived: 0xbfcceda0

问题是-当基类不是多态的而派生类是多态时,为什么基类和派生类中的“此”地址不同?

最佳答案

当您拥有一个类的多态单继承体系时,大多数(如果不是全部)编译器都遵循的典型约定是,该层次结构中的每个对象都必须以VMT指针(指向虚拟方法表的指针)开头。在这种情况下,VMT指针会被早期引入对象内存布局:通过多态层次结构的根类,而所有较低的类仅继承它并将其设置为指向其正确的VMT。在这种情况下,任何派生对象中的所有嵌套子对象都具有相同的this值。这样,通过读取*this处的内存位置,编译器可以立即访问VMT指针,而不管实际的子对象类型如何。这正是您上一次实验中发生的情况。使根类成为多态时,所有this值都匹配。

但是,当层次结构中的基类不是多态的时,它不会引入VMT指针。 VMT指针将由层次结构中较低位置的第一个多态类引入。在这种情况下,一种流行的实现方法是在层次结构的非多态(上部)部分引入的数据之前插入VMT指针。这是您在第二个实验中看到的。 Derived的内存布局如下所示

+------------------------------------+ <---- `this` value for `Derived` and below
| VMT pointer introduced by Derived  |
+------------------------------------+ <---- `this` value for `Base` and above
| Base data                          |
+------------------------------------+
| Derived data                       |
+------------------------------------+

同时,层次结构的非多态(上部)部分中的所有类对任何VMT指针一无所知。 Base类型的对象必须以数据字段Base::x开头。同时,层次结构的多态(下部)部分中的所有类都必须以VMT指针开头。为了满足这两个要求,编译器在将对象指针值从一个嵌套基础子对象到另一个嵌套基础子对象上上下转换时,被迫调整对象指针值。这立即意味着跨多态/非多态边界的指针转换不再是概念性的:编译器必须添加或减去一些偏移量。

来自层次结构的非多态部分的子对象将共享其this值,而来自层次结构的多态部分的子对象将共享其自己的不同的this值。

在沿层次结构转换指针值时必须添加或减去一些偏移量并不罕见:在处理多继承层次结构时,编译器必须始终这样做。但是,您的示例显示了如何在单继承层次结构中也可以实现它。

加/减效果也将在指针转换中显示
Derived *pd = new Derived;
Base *pb = pd;
// Numerical values of `pb` and `pd` are different if `Base` is non-polymorphic
// and `Derived` is polymorphic

Derived *pd2 = static_cast<Derived *>(pb);
// Numerical values of `pd` and `pd2` are the same

09-10 03:30
查看更多