Virtual Table

C++对象模型——吴泰

C/C++杂记

C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现

C++ 多继承和虚继承的内存布局 【已翻译100%】 (虚继承参考,推荐)

图说C++对象模型:对象内存布局详解

VTable Notes on Multiple Inheritance in GCC C++ Compiler v4.0.1

Itanium C++ ABI

What is the VTT for a class?

===================================================

Why do we not have a virtual constructor in C++?

1.vptr变量是在构造函数中进行初始化的。又因为要想执行虚函数必须通过vptr变量找到虚函数表。(在构造函数初始化vptr变量之前是不会调用虚函数的)如果可以定义虚构造函数,就陷入了先有鸡还是先有蛋的问题。

2.似乎没有虚构造函数的需求

更多回答请参考 这个链接

虚析构函数

执行任何正常的析构函数:

把析构函数写成虚函数的作用,和普通虚函数的作用是一样的。

GCC编译的时候,虚表中会有两个虚析构函数。
Virtual TableVirtual Table

The entries for virtual destructors are actually pairs of entries. The first destructor, called the complete object destructor, performs the destruction without calling delete() on the object. The second destructor, called the deleting destructor, calls delete() after destroying the object. Both destroy any virtual bases; a separate, non-virtual function, called the base object destructor, performs destruction of the object but not its virtual base subobjects, and does not call delete().

View Code
VS环境下的编译似乎只有一个虚析构函数。

虚继承

虚继承的实现与具体编译器相关,不同编译器实现有所不同。

class A {
public:
  int a;
  virtual void v();
};

class B : public virtual A {
public:
  int b;
  virtual void w();
};

class C : public virtual A {
public:
  int c;
  virtual void x();
};

class D : public B, public C {
public:
  int d;
  virtual void y();
};

                                   +-----------------------+
                                   |   20 (vbase_offset)   |
                                   +-----------------------+
                                   |     0 (top_offset)    |
                                   +-----------------------+
                                   | ptr to typeinfo for D |
                      +----------> +-----------------------+
d --> +----------+    |            |         B::w()        |
      |  vtable  |----+            +-----------------------+
      +----------+                 |         D::y()        |
      |     b    |                 +-----------------------+
      +----------+                 |   12 (vbase_offset)   |
      |  vtable  |---------+       +-----------------------+
      +----------+         |       |    -8 (top_offset)    |
      |     c    |         |       +-----------------------+
      +----------+         |       | ptr to typeinfo for D |
      |     d    |         +-----> +-----------------------+
      +----------+                 |         C::x()        |
      |  vtable  |----+            +-----------------------+
      +----------+    |            |    0 (vbase_offset)   |
      |     a    |    |            +-----------------------+
      +----------+    |            |   -20 (top_offset)    |
                      |            +-----------------------+
                      |            | ptr to typeinfo for D |
                      +----------> +-----------------------+
                                   |         A::v()        |
                                   +-----------------------+


class A {
public:
  int a;
};

class B : public virtual A {
public:
  int b;
  virtual void w();
};

class C : public virtual A {
public:
  int c;
};

class D : public B, public C {
public:
  int d;
  virtual void y();
};


                                   +-----------------------+
                                   |   20 (vbase_offset)   |
                                   +-----------------------+
                                   |     0 (top_offset)    |
                                   +-----------------------+
                                   | ptr to typeinfo for D |
                      +----------> +-----------------------+
d --> +----------+    |            |         B::w()        |
      |  vtable  |----+            +-----------------------+
      +----------+                 |         D::y()        |
      |     b    |                 +-----------------------+
      +----------+                 |   12 (vbase_offset)   |
      |  vtable  |---------+       +-----------------------+
      +----------+         |       |    -8 (top_offset)    |
      |     c    |         |       +-----------------------+
      +----------+         |       | ptr to typeinfo for D |
      |     d    |         +-----> +-----------------------+
      +----------+
      |     a    |
      +----------+

vbase_offset指的是到基类A的偏移。

普通继承在调用virtual function时会进行查表,而存取member可以在编译期决议完成。

虚继承在调用virtual function和存取member时都会进行查表。

但无论是普通继承还是虚继承,经由对象调用(非指针、引用)都可以优化成直接存取操作,因为对象的类型不会改变。
原文链接: https://www.cnblogs.com/dirge/p/9024916.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/273935

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 下午11:58
下一篇 2023年2月14日 下午11:59

相关推荐