2026年物业门控五金耗材推荐榜:中企创联工业品,小区/写字楼/物业多场景门控配件全覆盖
2026/3/1 13:31:04
在 C++ 中,虚函数(virtual function)和普通函数(non-virtual function)在行为机制和用途上有重要区别。下面从多个维度进行对比分析:
| 特性 | 虚函数 | 普通函数 |
|---|---|---|
| 动态绑定 | 运行时多态(动态绑定) | 编译时绑定(静态绑定) |
| 继承行为 | 可被派生类重写(override) | 派生类同名函数会隐藏基类函数 |
| 内存开销 | 有虚函数表(vtable)开销 | 无额外开销 |
| 调用效率 | 稍慢(需通过虚表指针查找) | 更快(直接调用) |
| 关键字 | 使用virtual声明 | 无需特殊关键字 |
classBase{public:voidnormalFunc(){cout<<"Base normal\n";}// 普通函数virtualvoidvirtualFunc(){cout<<"Base virtual\n";}// 虚函数};classDerived:publicBase{public:voidnormalFunc(){cout<<"Derived normal\n";}voidvirtualFunc()override{cout<<"Derived virtual\n";}};intmain(){Base*ptr=newDerived();ptr->normalFunc();// 输出: Base normal(静态绑定)ptr->virtualFunc();// 输出: Derived virtual(动态绑定)deleteptr;return0;}classBase{public:voidshow(){cout<<"Base show\n";}virtualvoiddisplay(){cout<<"Base display\n";}};classDerived:publicBase{public:// 隐藏基类的 show(),不是重写voidshow(){cout<<"Derived show\n";}// 重写虚函数voiddisplay()override{cout<<"Derived display\n";}};intmain(){Derived d;Base&b=d;d.show();// Derived showb.show();// Base show(静态绑定)d.display();// Derived displayb.display();// Derived display(动态绑定)}classWithVirtual{intx;public:virtualvoidfunc1(){}virtualvoidfunc2(){}};// 大小通常为 8(指针) + 4(int) + 对齐 = 16 字节(64位系统)classWithoutVirtual{intx;public:voidfunc1(){}voidfunc2(){}};// 大小通常为 4 字节每个包含虚函数的类都有一个虚函数表(vtable),对象包含指向该表的指针(vptr):
classAnimal{public:virtualvoidspeak()=0;virtualvoideat(){cout<<"Animal eating\n";}voidbreathe(){cout<<"Animal breathing\n";}// 普通函数};classDog:publicAnimal{public:voidspeak()override{cout<<"Woof!\n";}voideat()override{cout<<"Dog eating\n";}};// 内存布局示意:// Dog对象: [vptr] -> [&Dog::speak, &Dog::eat]// 其他成员变量...#include<iostream>usingnamespacestd;// 基类classShape{protected:doublex,y;public:Shape(doublex,doubley):x(x),y(y){}// 普通函数:所有形状共享相同实现voidmove(doubledx,doubledy){x+=dx;y+=dy;cout<<"Shape moved\n";}// 虚函数:不同形状有不同实现virtualdoublearea()const{cout<<"Shape area (should override)\n";return0.0;}// 纯虚函数:强制派生类实现virtualvoiddraw()const=0;virtual~Shape(){}// 虚析构函数,确保正确释放资源};// 派生类classCircle:publicShape{doubleradius;public:Circle(doublex,doubley,doubler):Shape(x,y),radius(r){}// 重写虚函数doublearea()constoverride{return3.14159*radius*radius;}voiddraw()constoverride{cout<<"Drawing circle at ("<<x<<", "<<y<<") with radius "<<radius<<endl;}// 新增普通函数(不涉及多态)doublegetRadius()const{returnradius;}};intmain(){Circlecircle(10,20,5);Shape*shapePtr=&circle;// 普通函数:静态绑定circle.move(1,1);// Circle 对象调用shapePtr->move(1,1);// Shape 指针调用,相同结果// 虚函数:动态绑定cout<<"Circle area: "<<circle.area()<<endl;// Circle 实现cout<<"Via pointer: "<<shapePtr->area()<<endl;// Circle 实现// 纯虚函数circle.draw();shapePtr->draw();return0;}final禁止进一步重写