“= 0”是c++中声明纯虚函数的唯一语法标记,用于告知编译器该函数仅定义接口契约、基类不提供实现且类变为抽象类,不可实例化;它不参与运行时计算,不可替换为nullptr或delete,纯虚析构函数是唯一需同时声明=0并定义函数体的特例。

“= 0”不是赋值,是编译器识别抽象接口的标记符号。它不参与运行时计算,也不表示数值零,纯粹是 C++ 语法层面向编译器发出的信号:「这个虚函数只负责定义契约,基类不提供实现,也不允许用它构造对象」。
为什么不能用其他写法代替 = 0
常见误解是把 = 0 当成初始化或默认值——它既不是默认实现,也不能换成 = nullptr 或 = delete。C++ 标准硬性规定:只有 = 0 才能声明纯虚函数。
-
virtual void draw() = nullptr;→ 编译错误:非类型上下文不允许用nullptr -
virtual void draw() = delete;→ 这是显式删除函数,和虚函数机制无关,也不会让类变成抽象类 -
virtual void draw() {};→ 变成有默认实现的虚函数,类可实例化,失去强制重写的约束力
= 0 同时触发两个关键行为
这个符号看似简单,实则一石二鸟:
- 告诉编译器:该函数进入虚函数表(vtable),但对应槽位填的是一个“兜底陷阱函数”(比如调用时 abort 或抛异常),防止未重写就误调
- 让整个类立即变成抽象类:
class Shape { virtual void area() = 0; };→Shape s;编译直接报错C2259: cannot instantiate abstract class
纯虚析构函数是个特例:必须写 = 0,也必须写函数体
这是唯一允许、且必须同时做两件事的纯虚函数:
- 声明仍需
virtual ~Base() = 0;(否则类不是抽象类) - 但必须在类外提供定义:
Base::~Base() { },否则链接失败 - 原因:派生类析构时会隐式调用基类析构函数,没函数体就找不到符号
其他纯虚函数绝对不要写函数体;唯独析构函数,= 0 和函数体缺一不可。
真正容易被忽略的点在于:= 0 的作用完全发生在编译期,它不生成任何运行时开销,也不影响 vtable 布局结构——但它像一道闸门,把“口头约定”锁进了类型系统里。一旦漏掉,或者误加实现,契约就失效了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











