糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > C++中虚函数与多态实现

C++中虚函数与多态实现

时间:2022-05-31 07:13:28

相关推荐

C++中虚函数与多态实现

多态,什么是多态?在计算机语言中,多态就是指一个接口或者方法,有多种展现形态。在C++中,通过父类指针调用子类方法,可以让父类指针有多种形态。

C++中实现多态的方式有:虚函数,重载,模板,绑定等。此次主要讨论虚函数实现多态。

例子:即使类继承,也没有多态。

classanimal

{

public:

voidcry()

{

cout<<"animalcry"<<endl;

}

voidbreathe()

{

cout<<"animalbreathe"<<endl;

}

};

classbrid:publicanimal

{

public:

voidbreathe()

{

cout<<"bridbubble"<<endl;

}

};

voidmain()

{

bridbd;

animal*a=&bd;

a->breathe();

}

答案是输出:animalbreathe

结果分析:此时为什么类继承了,却没有实现多态了?

1.从程序编译的角度看:

编译器在编译的时候,要先确定每个对象调用的函数地址,成为早期绑定,当我们没用虚函数时,将brid对象赋给animal时:animal*a=&bd;编译器进行了类型转换,此时C++编译器认为变量a保存的就是animal对象的地址,所以执行a->breathe();时,调用的是基类对象的方法。

2.从对象在内存中的布局来看。

在构造子类brid对象时,先用父类的构造函数去构造父类的对象,再用子类的构造函数完成自身新增部分的构造,当我们将brid对象转换成父类对象时,存在自动类型转换的过程,将子类转换成了父类对象,所以利用类型转换后的对象指针去调用它的方法时,也就只能调用他所对应在内存的方法了。

利用虚函数解决上面的问题,实现多态。

在基类中声明成员函数时,使用virtual关键字,声明为虚函数,程序在运行时才会去决定对象的类型以及所要调用的函数(迟绑定技术),从而得以实现多态。

注意:函数一旦在基类中声明为virtual,在所有的派生类中,该函数都是虚函数,只是不再显式声明为virtual.

将函数父类breathe()函数前加virtual,再次运行,结果为:birdbubble。

结果分析:

1.只要类中有虚函数,编译器会主动为类提供虚表:

编译器为每个类的对象提供一个虚表指针,这个指针指向对象所属类的虚表。虚表中记录的是每个虚函数调用的函数入口地址,虚表初始化时,虚函数的入口地址为父类虚函数地址,当子类继承父类时,重写虚函数,虚表中的虚函数入口地址更新为子类虚函数的地址。在程序运行时,根据对象的类型去初始化vptr,从而让vptr正确的指向所属类的虚表,从而在调用虚函数时,就能够找到正确的函数。

由于a实际指向的对象类型是brid,因此vptr指向的brid类的vtable,当调用a->breathe()时,根据虚表中的函数地址找到的就是brid类的breathe()函数。

2.由于对象调用的虚函数都是通过虚表指针来索引的,也就决定了虚表指针的正确初始化是非常重要的。换句话说,在虚表指针没有正确初始化之前,我们不能够去调用虚函数。那么虚表指针在什么时候,或者说在什么地方初始化呢?

答案是在构造函数中进行虚表的创建和虚表指针的初始化。

还记得构造函数的调用顺序吗,在构造子类对象时,要先调用父类的构造函数,此时编译器只“看到了”父类,并不知道后面是否后还有继承者,它初始化父类对象的虚表指针,该虚表指针指向父类的虚表。当执行子类的构造函数时,子类对象的虚表指针被初始化,指向自身的虚表。

如果觉得《C++中虚函数与多态实现》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。