虚函数表

目录

说到c++的运行时多态机制,就不能不提继承和virtual关键字,继承和virtual关键字使子类能够重载父类的方法,实现运行时多态。
运行时多态的背后机制就是虚函数表,下面进行简单的介绍:

  1. 当一个类中的方法使用了virtual时,该类的对象就会额外多出一个虚函数表地址指针(该指针指向虚函数表,因此含有虚函数的对象会额外多出一个sizeof(指针)的空间)。
  2. 虚函数表入口地址位于对象的起始地址处。
  3. 虚函数表中存放了类的各个虚函数,虽然类一样,但是每个对象都保存了指向虚函数表地址的指针。

下面看下代码 test.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <thread>
using namespace std;
class Empty{
};
class Base{
public:
virtual void func1() { cout << "Base func1" << endl;}
virtual void func2() { cout << "Base func2" << endl;}
};
int main()
{
cout << "sizeof(Empty) = " << sizeof(Empty) << endl;
cout << "sizeof(Base) = " << sizeof(Base) << endl;
typedef void(*Func)();
Base object;
cout << "address of vtable = " << (long *)*(long*)(&object) << endl; //虚函数表位于对象起始地址处
Func func1 = (Func)*(long *)*(long*)(&object); //虚函数表地址的第一个地址
cout << "address of first virtual function = " << &func1 << endl; //虚函数表位于对象起始地址处
func1();
Func func2 = (Func)*((long *)*(long*)(&object) + 1); //虚函数地址偏移一位——long *指针的大小,32位系统为4字节,64位系统为8字节
cout << "address of second virtual function = " << &func2 << endl; //虚函数表位于对象起始地址处
func2();
return 0;
}

编译:g++ test.cpp 然后./a.out运行之,结果如下:

1
2
3
4
5
6
7
sizeof(Empty) = 1
sizeof(Base) = 8
address of vtable = 0x1068f70d8
address of first virtual function = 0x7fff5930aa58
Base func1
address of second virtual function = 0x7fff5930aa50
Base func2

引申:
c++中的重载分为静态重载,即在编译期决定了使用的函数原型,这种重载一般通过函数参数的差异(可以是参数的个数或者参数类型)来实现,如:

1
2
int add(int a, int b);
double add(double a, double b);
本站总访问量