C++多态实现原理
Posted Windows开发
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++多态实现原理相关的知识,希望对你有一定的参考价值。
多态是C++的一个重要特性,本文将深入介绍C++编译器是如何实现C++多态特性。
先看一段涉及多态的代码。
using namespace std;
class BaseClass
{
public:
virtual ~BaseClass() {}
virtual void VirtualFunction1() {
cout << "I am base virtual function 1" << endl;
}
virtual void VirtualFunction2() {
cout << "I am base virtual function 2" << endl;
}
void NonVirtualFunction() {
cout << "I am base non virtual function" << endl;
}
private:
int m_nBaseField = 0;
};
class SubClass : public BaseClass
{
public:
virtual ~SubClass() {}
virtual void VirtualFunction1() override {
cout << "I am subclass function 1, override base class" << endl;
}
void NonVirtualFunction() {
cout << "I am subclass non virtual function" << endl;
}
private:
int m_nSubClassField = 0;
};
int main()
{
BaseClass baseClass;
SubClass subClass;
BaseClass* pBaseClass = &baseClass;
pBaseClass->VirtualFunction1();
pBaseClass = &subClass;
pBaseClass->VirtualFunction1();
pBaseClass->NonVirtualFunction();
return 0;
}
如上示例代码,定义基类BaseClass,BaseClass定义了虚析构函数、虚函数VirtualFunction1、虚函数VirtualFunction2、非虚函数NonVirtualFunction。
然后定义子类SubClass继承于BaseClass,覆盖重写BaseClass的虚析构函数、虚函数VirtualFunction1、函数NonVirtualFunction,未覆盖重写BaseClass的虚函数VirtualFunction2。
Main函数定义了两个对象baseClass和subClass,定义了BaseClass指针pBaseClass,先让pBaseClass指向baseClass对象,调用VirtualFunction1,然后让pBaseClass指向subClass,调用VirtualFunction1和NonVirtualFunction。
下面是输出结果:
从输出结果知:
第一,pBaseClass指向baseClass对象,调用VirtualFunction1时,是调用BaseClass::VirtualFunction1。当pBaseClass指向subClass对象,调用VirtualFunction1时,是调用SubClass::VirtualFunction1。也就是说,pBaseClass同样调用VirtualFunction1,但是会因为pBaseClass指向的对象不同,而产生不同的行为(调用不同的方法),这就是多态。
第二,pBaseClass指向subClass对象,调用NonVirtualFunction时,调用的是BaseClass::NonVirtualFunction,而不是SubClass::NonVirtualFunction。
接下来将重点解释下这两个结论,首先让我们看下baseClass和subClass这两个对象的内存布局。
subClass继承于baseClass,内存布局上首先是baseClass的__vfptr和数据成员m_nBaseField,然后是SubClass定义的数据成员m_nSubClassField。subClass的__vfptr的值与baseClass的__vfptr的值不同,说明它们指向的虚函数表是不一样的。由于subClass没有新增虚函数,所以虚函数表也是三个元素与BaseClass的虚函数个数相同。但是,subClass覆盖重写了baseClass的虚析构函数和VirtualFunction1,所以第一和第二个元素的值不同,指向的是SubClass对应的虚函数。由于VirtualFunction2未被覆盖重写,所以第三个元素的值与BaseClass的虚函数表的第三个元素的值相同,都指向BaseClass::VirtualFunction2。
NonVirtualFunction不是虚函数,所以没有在虚函数表中。
接下来,我将结合虚函数表和汇编代码对上面的结论进行解释说明。
指针pBaseClass指向subClass对象,为什么调用VirtualFunction1方法时,是调用subClass::VirtualFunction1呢?让我们先看下汇编代码。
其次,读取eax所指向的内存的值放入寄存器edx,也就是pBaseClass->__vfptr的值(虚函数表指针的值)。
最后,call eax,也就是call VirtualFunction1。
以上是关于C++多态实现原理的主要内容,如果未能解决你的问题,请参考以下文章
9-3:C++多态之多态的实现原理之虚函数表,虚函数表指针静态绑定和动态绑定