每个包含了虚函数的class会包含一个虚函数表,对于C1和C2的虚函数表的结构如下:
- 非虚函数不会加入到虚函数表中
- 子类中如果对虚函数重写,虚函数表中会覆盖父类的虚函数
C1::~C1() |
C1::~f1() |
C1::~f2() |
C1::~f3() |
C2::~C2() |
C2::~f1() |
C1::~f2() |
C1::~f3() |
C2::~f5() |
class C1 {
public:C1();virtual ~C1();virtual void f1();virtual int f2(char c) const;virtual void f3(const string& s);void f4() const;
};class C2 : public C1 {
public:c2();virtual ~C2();virtual void f1();virtual void f5(char *str);
};
每一个拥有虚函数类的对象都包含一个虚函数指针,指向了该类的虚函数表:
- 虚表指针由编译器生成,插入的位置各个编译器不同,可能位于对象的头部,也可能是尾部
由于pC1指向的对象可能是C1的对象,也可是C2的对象,所以需要在运行期决定
编译器查找虚函数的过程会等效于下面的操作
void makeACall(C1 *pC1) {pC1->f1();// 等效于(*pC1->vptr[i])(pC1);
}