纯虚函数必须在子类中实现,否则派生类仍为抽象类;声明为virtual void f() = 0;,可带实现体但不自动调用;多态依赖基类指针或引用调用,需注意虚表开销与正确使用override。

纯虚函数声明后必须在子类中实现
纯虚函数本身没有函数体,只在基类中用 = 0 声明,它强制派生类提供具体实现。如果派生类没重写该函数,这个派生类依然是抽象类,无法实例化。
常见错误是忘记在子类中定义同签名函数,编译时会报类似 cannot declare variable 'x' to be of abstract type 的错误。
- 函数名、参数类型、const 修饰符、返回类型(协变除外)必须完全一致
- 子类中不必加
virtual或= 0,但加override是强烈推荐的(防止签名拼错) - 基类析构函数若含纯虚函数,建议也声明为
virtual,否则通过基类指针 delete 派生类对象会未定义行为
多态调用依赖基类指针或引用
纯虚函数本身不提供多态能力,真正触发动态绑定的是“通过基类指针/引用调用虚函数”这一操作。编译器在运行时根据实际对象类型查虚表,跳转到对应子类实现。
如果直接用子类对象调用(如 obj.func()),哪怕 func 是虚函数,也不会走虚调用路径——这是静态绑定。
- 必须用
Base* ptr = new Derived(); ptr->func();或Base& ref = derived_obj; ref.func(); - 传参时也需用指针或引用,值传递会切片(slicing),丢失派生类信息
- 使用智能指针(如
std::unique_ptr<base>)同样有效,本质仍是多态指针语义
纯虚函数可以有实现体,但不能自动调用
和很多人想的不同,C++ 允许给纯虚函数提供函数体,语法是声明后加定义(不在类内,在类外):
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
struct Base {
virtual void func() = 0;
};
void Base::func() { /* 实现体 */ }
但这不会改变“必须重写”的规则,子类仍要自己实现;不过子类实现里可以用 Base::func() 显式调用基类版本,常用于公共逻辑复用。
- 这种写法少见,容易让人误以为“不重写也能用”,务必谨慎
- 接口设计上,更推荐把公共逻辑抽成 protected 普通成员函数,由纯虚函数调用
- 纯虚析构函数是个例外:必须提供实现(哪怕空),否则链接失败
注意 vtable 和对象布局带来的隐含成本
含纯虚函数的类会生成虚表,每个对象增加一个虚指针(通常 8 字节)。这对内存敏感场景(如嵌入式、高频小对象)有实际影响。
另外,虚函数调用比普通函数多一次间接寻址,现代 CPU 分支预测做得好,一般差异不大,但在 tight loop 中仍可测出开销。
- 不要只为“看起来像接口”而滥用纯虚函数;无多态需求时,用普通函数或模板更轻量
- 避免在纯虚函数中做耗时操作,因为调用方往往不预期延迟
- 若子类实现只是转发或简单计算,编译器可能无法内联,
final修饰子类可帮助优化
纯虚函数实现多态的关键不在“虚”,而在“被基类指针/引用调用时能动态分发”。最容易忽略的是:没用指针/引用、忘了 override、或者误以为纯虚函数体能自动继承。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










