说到c++的运行时多态机制,就不能不提继承和virtual关键字,继承和virtual关键字使子类能够重载父类的方法,实现运行时多态。
运行时多态的背后机制就是虚函数表,下面进行简单的介绍:
- 当一个类中的方法使用了virtual时,该类的对象就会额外多出一个虚函数表地址指针(该指针指向虚函数表,因此含有虚函数的对象会额外多出一个sizeof(指针)的空间)。
- 虚函数表入口地址位于对象的起始地址处。
- 虚函数表中存放了类的各个虚函数,虽然类一样,但是每个对象都保存了指向虚函数表地址的指针。
下面看下代码 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); 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);
|