C++的多态(polymorphism)怎么实现的?

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; }
};

Untitled

情况二(单继承):

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; }
};

Untitled

情况三(多重继承):

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; }
};