多重继承C++

4

有几个问题与此相关,但我仍然不清楚。考虑这个多重继承。

class Base1 
{ 
   public: 
     Base1(); 
     virtual ~Base1(); 
     virtual void speakClearly(); 
     virtual Base1 *clone() const; 
   protected: 
     float data_Base1; 
}; 

class Base2 
{ 
   public: 
     Base2(); 
     virtual ~Base2(); 
     virtual void mumble(); 
     virtual Base2 *clone() const; 
   protected: 
     float data_Base2; 
}; 

class Derived : public Base1, public Base2 
{ 
   public: 
     Derived(); 
     virtual ~Derived(); 
     virtual Derived *clone() const; 
   protected: 
     float data_Derived; 
}; 

考虑以下两个陈述:

Base1 *pbase1 = new Derived; 
Base2 *pbase2 = new Derived;

《C++对象模型内部揭秘》一书指出,在优化中可能存在一个问题。

pbase1子对象和Derived共享同一个vtable。这是书中的原话。

“由于Base1是最左边的,它已经指向了Derived类对象的开头”。

这是如何发生的呢?如果我改变继承的顺序,这会改变吗?

class Derived : public Base2, public Base1

但是我不理解编译器是如何实现这一点的。有人能解释一下pbase1和derived如何共享同一个v_table吗?


由于v_tables通常在数组中实现为指针偏移量(但不一定如此),我猜测它们可以共享Derived类对象的v_table,因为编译器可以在编译时合并Base1Base2的v_tables。这有什么奇怪的呢? - Germán Diago
2个回答

2

这都是实现定义的,但通常情况下,编译器会将Derived布局为:

Base1: vptr
Base1: data
Base2: vptr
Base2: data
Derived: data
Derived的地址是整个对象的地址,因此与Base1的物理地址相同。 Derived的vtable的初始部分将与Base1的相同,并且Base1:vptr实际上将指向Derived的vtable。
如果在声明中颠倒Base1Base2,编译器将反转它们的角色。 (通常如此。标准中没有任何阻止编译器按字母顺序排列基类或将派生数据放在第一位的内容,但我从未听说过这样做的编译器。)

1

将类想象为具有一些“隐藏成员”,这些成员在您声明的成员之前,给出以下布局:

  • vtable指针
  • 第一个基类
    • 它的vtable指针
    • 它自己的成员
  • 第二个基类
    • 它的vtable指针
    • 它自己的成员
  • 派生类成员

现在问题是“指针应该指向哪里?”

由于所有函数都可以在最终派生对象中使用,因此可以为其创建一个“函数指针数组”,用于:

  • dtor,
  • speakClearly
  • clone
  • mumble

该表对于DerivedBase1的工作方式相同(只需忽略最后一行),但是对于Base2则不然,它只需要查看:

  • dtor
  • clone
  • mumble

与先前的索引不同(这就是为什么它需要不同的原因)。

由于这个事实,无需区分派生表和第一基础表实例(当然,我们也可以从最后一个基础表开始进行同样的推理,并区分前面的表...但必须有一个起点)
编译器将因此“压缩”实现,通过创建仅具有第一个基础虚函数及所有其他虚函数的表,并为其他基础表创建其他不同的表,然后将初始化所有指向最派生实现的虚函数指针。
布局将是
1. 派生vtable 2. Base1成员 3. Base2与Derived vtable 4. Base2成员 5. 派生成员
现在,new Derived只会创建那个草图,并且:
- 如果给定Derived*,将使其指向1。 - 如果给定Base1*,将使其指向1。 (就像Derived一样,但“更短”) - 如果给定Base2*,将使其指向3。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接