C++使用了一种动态绑定的技术(非虚函数一般都是静态绑定,而虚函数都是动态绑定)。这个技术的核心是虚函数表(简称虚表)(Virtual Table, or VTable)。
对于一个类来说,如果类中存在虚函数,那么该类的大小就会多4个字节,这4个字节就是一个指针的大小,这个指针指向该类的虚函数表,称作虚函数指针 (virtual table pointer, vpointer or VPTR)。
虚函数(Virtual Function)是通过一张虚函数表来实现的。简称为V-Table。在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。在有虚函数的类的实例中分配了虚函数指针的内存,所以,当用父类的指针来操作一个子类的时候,这张虚函数表就像一个地图一样,指明了实际所应该调用的函数。
每个包含了虚函数的类都包含一个虚表。同一个类的不同实例共用一个虚表。
虚函数表是在编译的过程中创建的。
虚函数指针是在实例化对象时创建的,所以是在运行的过程中创建的。
实例化对象时,先给虚函数指针赋值,再执行构造函数。
ref:https://cloud.tencent.com/developer/article/1599283
情况一:
class Base1 {
public:
virtual void A() { cout << "Base1 A()" << endl; }
virtual void B() { cout << "Base1 B()" << endl; }
virtual void C() { cout << "Base1 C()" << endl; }
};
class Derive : public Base1{
public:
virtual void MyA() { cout << "Derive MyA()" << endl; }
};
情况二(单继承):
class Base1 {
public:
virtual void A() { cout << "Base1 A()" << endl; }
virtual void B() { cout << "Base1 B()" << endl; }
virtual void C() { cout << "Base1 C()" << endl; }
};
class Derive : public Base1{
public:
virtual void MyA() { cout << "Derive MyA()" << endl; }
virtual void B() { cout << "Derive B()" << endl; }
};
情况三(多重继承):
class Base1 {
public:
virtual void A() { cout << "Base1 A()" << endl; }
virtual void B() { cout << "Base1 B()" << endl; }
virtual void C() { cout << "Base1 C()" << endl; }
};
class Base2 {
public:
virtual void D() { cout << "Base2 D()" << endl; }
virtual void E() { cout << "Base2 E()" << endl; }
};
class Derive : public Base1, public Base2{
public:
virtual void A() { cout << "Derive A()" << endl; } // 覆盖Base1::A()
virtual void D() { cout << "Derive D()" << endl; } // 覆盖Base2::D()
virtual void MyA() { cout << "Derive MyA()" << endl; }
};