C++中的虚函数的作用主要是实现了多态的机制。
虚函数是通过一张虚函数表(Virtual Table)实现的。在这个表中,主要是一个类的虚函数地址表,这张表解决了继承和覆盖等问题。就像一张地图一样,指明了指针实际所应该调用的函数。
①我们在声明了一个有虚函数的类的对象同时,这个对象被添加了一个隐式成员。该成员保存了指向虚函数地址数组的指针。
②只要包含虚函数的类就会有一个虚函数表,当这个类是基类时,它的派生类也会有相应的虚函数表。当一个类有多个对象的时候,这些对象共享一个虚函数表。
③虚函数表是编译器生成的,程序运行时被载入内存。
示意代码:
#include
using namespace std;
class A
{
public:
int i;
virtual void func() {}
virtual void func2() {}
};
class B : public A
{
int j;
void func() {}
};
int main()
{
A a;
B b;
size_t len_a = sizeof(a);
size_t len_b = sizeof(b);
cout << len_a << ", " << len_b<
示意图:
①正常的函数调用:
②虚函数调用:
而虚函数调用与此完全相同,唯一的区别就是编译时不知道函数的地址,而是,
从上面的分析可以看出来,虚函数可能会造成性能损失:
● 构造函数必须初始化vptr。
● 虚函数是通过指针间接调用的,所以必须先得到指向虚函数表的指针,然后再获得正确的函数偏移量。
● 内联是在编译时决定的。编译器不可能把运行时才解析的虚函数设置为内联。
虚函数其实最主要的性能开销在于它阻碍了编译器内联函数和各种函数级别的优化,导致性能开销较大。如果代码中使用了更多的虚函数,编译器能优化的代码就越少,性能就越低。所以,评估虚函数的性能损失就是评估无法内联该函数所造成的损失。这种损失的代价并不固定,它取决于函数的复杂程度和调用频率。
虚函数通常通过虚函数表来实现,在虚表中存储函数指针,实际调用时需要间接访问,这需要多一点时间。然而这并不是虚函数速度慢的主要原因,真正原因是编译器在编译时通常并不知道它将要调用哪个函数,所以它不能被内联优化和其它很多优化,因此就会增加很多无意义的指令(准备寄存器、调用函数、保存状态等)。真正的问题不是虚函数,而是那些不必要的间接调用。
通常,使用虚函数没问题,它的性能开销也不大,而且虚函数在面向对象代码中有强大的作用。但是不能无脑使用虚函数,特别是在性能至关重要的或者底层代码中,而且大项目中使用多态也会导致继承层次很混乱。
页面更新:2024-03-30
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号