C++中多态原理:VPTR虚函数表
一多态产生的条件:
1有子类继承父类
2存在虚函数重写
3父类指针指向子类对象,或是父类引用子类对象
二虚函数表和vptr指针
1当类中声明虚函数时,编译器会在类中生成一个虚函数表
2虚函数表示一个存储类成员函数指针的数据结构
3虚函数表是由编译器自动生成与维护的
4virtual成员函数会被编译器放入虚函数表中
5存在虚函数时,每个对象中都有一个指向虚函数表的指针(vptr指针)
三多态中的动态联编:
在符合多态条件下, 当调用类的成员函数时,vptr指针会先在虚函数表中依次查找,直到找到符合的函数。
说明:1通过虚函数表指针vptr调用重写函数是在程进行的序运行时,因此需要寻址操作才能确定真正应该调用的函数。而普通成员函数时在编译时就确定了调用的函数。所以在效率上,虚函数的效率要低得多。
2处于效率考虑,没必要将所有成员函数 都声明为虚函数
3C++编译器,执行虚函数,不需要区分是子类对象还是父类对象,而是直接通过p的vptr指针指向的对象函数执行即可。
四构造函数中能否调用虚函数实现多态的问题:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Parent
{
public:
Parent(int a = 0)
{
this->a = a;
print();
}
virtual void print()
{
cout << "I'm Parent" << endl;
}
private:
int a;
};
class Child :public Parent
{
public:
Child(int a = 0, int b = 0) :Parent(a)
{
this->b = b;
print();
}
virtual void print()
{
cout << "I'm Son" << endl;
}
private:
int b;
};
void HowToPlay(Parent* base)
{
base->print();
}
int main(void)
{
Child c1;
HowToPlay(&c1);
system("pause");
return 0;
}
打印结果:

父类对象指向子类,父类构造函数中的虚函数print答应的依然是父类的成员函数,这个过程没有发生多态。调用HowToPlay时,发生多态。所以这种情况下,构造函数中调用虚函数是不能发生多态的。
关于vptr指针的初始化,是分部进行的,先指向并初始化父类VPTR表,再指向并初始化子类VPTR表。
浙公网安备 33010602011771号