纯虚函数声明必须为virtual 返回类型 函数名(参数列表) = 0;,漏写=0则变为普通虚函数;含纯虚函数的类为抽象类,不可实例化,但可定义指针或引用;派生类须全部公有实现纯虚函数才能实例化;纯虚函数可在类外定义实现,但仅能显式作用域调用。

纯虚函数的声明语法必须带 = 0
纯虚函数不是“没实现的普通虚函数”,而是语法上明确标记为“强制派生类覆盖”的函数。写法只有一种:virtual 返回类型 函数名(参数列表) = 0;。漏掉 = 0 就变成普通虚函数,类也不会被自动视为抽象类。
常见错误包括:
- 写成
virtual void func() {}(有空实现,不是纯虚) - 写成
virtual void func() = 0.0;或= NULL(语法错误,只认= 0) - 在类外定义时加
= 0(不允许,= 0只能出现在类内声明中)
抽象类不能实例化,但可以定义指针或引用
只要类中至少有一个纯虚函数,它就是抽象类。此时直接写 MyAbstract obj; 会触发编译错误,典型提示是:error: cannot declare variable 'obj' to be of abstract type。
正确用法是通过多态接口操作:
立即学习“C++免费学习笔记(深入)”;
-
MyAbstract* ptr = new Derived();(指针指向派生对象) -
MyAbstract& ref = derived_obj;(引用绑定派生对象) - 作为函数参数类型:
void process(const MyAbstract& obj);
注意:抽象类的构造函数和析构函数仍可被调用(派生类构造时会调),所以建议把析构函数也声明为 virtual ~MyAbstract() = 0;,并提供定义(哪怕空实现),否则可能引发未定义行为。
派生类必须实现所有纯虚函数,否则仍是抽象类
如果派生类只实现了部分纯虚函数,或者把某个纯虚函数声明为 private,它依然无法实例化。编译器不会报错说“少实现”,而是在你尝试构造对象时才报抽象类错误,容易误判。
检查方法很简单:看派生类定义里是否每个纯虚函数都有对应签名的、非纯虚的 public 成员函数声明+定义。
- 签名必须完全一致(返回类型、函数名、参数类型、const 修饰符)
- 不能靠返回类型协变“蒙混”(除非是虚析构函数或指针/引用类型的返回值)
- 即使基类函数是
const,派生类实现也必须带const,否则算重载而非重写
纯虚函数可以有实现,但必须在类外定义
很多人以为纯虚函数“不能有函数体”,其实可以——只是不能在类内写实现,必须像普通成员函数一样在类外定义。这种写法常用于提供默认逻辑,同时强制派生类“显式选择”是否复用。
例如:
class Shape {
public:
virtual double area() const = 0;
};
double Shape::area() const { return 0.0; } // 合法:类外定义
调用方式受限:只能通过 Shape::area() 显式作用域调用,不能通过对象或指针的动态绑定调用(因为它是纯虚的)。实际项目中较少用,除非做模板钩子或调试桩。
容易忽略的一点:如果忘了给纯虚析构函数提供类外定义,链接阶段会报 undefined reference to 'Shape::~Shape()' —— 因为即使纯虚,析构函数仍会被派生类隐式调用。


















