c++对象虚表

虚表(virtual table)

The virtual table is actually quite simple, though it’s a little complex to describe in words. First, every class that uses virtual functions (or is derived from a class that uses virtual functions) is given it’s own virtual table. This table is simply a static array that the compiler sets up at compile time. A virtual table contains one entry for each virtual function that can be called by objects of the class. Each entry in this table is simply a function pointer that points to the most-derived function accessible by that class.

带有虚函数的类都有自己的虚表,虚表是编译器在编译时就确定的一个静态数组。虚表中包含每个虚函数的一个入口(函数指针),且这个函数指针是对象能访问到最近的一个函数指针。

Second, the compiler also adds a hidden pointer to the base class, which we will call *__vptr. *__vptr is set (automatically) when a class instance is created so that it points to the virtual table for that class. Unlike the *this pointer, which is actually a function parameter used by the compiler to resolve self-references, *__vptr is a real pointer. Consequently, it makes each class object allocated bigger by the size of one pointer. It also means that *__vptr is inherited by derived classes, which is important.

编译器会为基类设置一个隐藏的指针(*__vptr), 该指针是在类实例化时自动设置指向类的虚表的。

1、在进入构造函数时,虚表已经构建完成。

2、虚构时,虚表可以回滚。

3、虚表与虚表指针的区别:每个类只有一个虚表,每个对象实例都有个虚表指针。

如下:

 1 #include "stdafx.h"
2 #include <iostream>
3
4 class CBase
5 {
6 public:
7 CBase()
8 {
9 std::cout<<"CBase::CBase()"<<std::endl;
10 print();
11 //print1();
12 }
13 virtual ~CBase()
14 {
15 std::cout<<"CBase::~CBase()"<<std::endl;
16 print();
17 }
18 //virtual void print1() = 0;
19 virtual void print()
20 {
21 std::cout<<"CBase::print()"<<std::endl;
22 //print1();
23 }
24 };
25
26 class CDerived : public CBase
27 {
28 public:
29 CDerived()
30 {
31 std::cout<<"CDerived::CDerived()"<<std::endl;
32 print();
33 }
34
35 virtual ~CDerived()
36 {
37 std::cout<<"CDerived::~CDerived()"<<std::endl;
38 print();
39 }
40
41 virtual void print()
42 {
43 std::cout<<"CDerived::print()"<<std::endl;
44 }
45
46 virtual void print1()
47 {
48 std::cout<<"CDerived::print1()"<<std::endl;
49 }
50 };
51
52 void DoPrint(CBase* pBase)
53 {
54 pBase->print();
55 }
56 int _tmain(int argc, _TCHAR* argv[])
57 {
58 CBase* pBase = new CBase;
59 CDerived* pDerived = new CDerived;
60 CBase* pBase1 = pDerived;
61
62 std::cout<<"---------"<<std::endl;
63 DoPrint(pBase);
64 DoPrint(pDerived);
65 DoPrint(pBase1);
66 std::cout<<"---------"<<std::endl;
67
68 delete pBase;
69 delete pDerived;
70
71 return 0;
72 }

  输出:

CBase::CBase()

CBase::print()

CBase::CBase()

CBase::print()

CDerived::CDerived()

CDerived::print()

---------

CBase::print()

CDerived::print()

CDerived::print()

---------

CBase::~CBase()

CBase::print()

CDerived::~CDerived()

CDerived::print()

CBase::~CBase()

CBase::print()

原文地址:https://www.cnblogs.com/coderyoyo/p/2132626.html