抽象类必须包含至少一个纯虚函数(=0),否则可被实例化;派生类须完全重写所有纯虚函数(签名严格匹配)才能实例化;可含构造函数、成员变量和非纯虚函数,但析构函数应为virtual;纯接口类仅含纯虚函数,混合类可共享实现。

抽象类必须包含至少一个纯虚函数
抽象类不能被实例化,核心在于它至少有一个 virtual 函数被声明为纯虚(即赋值为 = 0)。编译器靠这个标记识别“未实现”,从而禁止直接构造对象。
常见错误是只写 virtual void func(); 而没加 = 0 —— 这只是虚函数,不是纯虚,类仍可实例化;或者误以为有虚析构函数就足够,其实不行,必须显式声明至少一个纯虚函数。
-
class Shape { virtual void draw() = 0; };→ 正确,Shape是抽象类 -
class Shape { virtual ~Shape() {} };→ 错误,Shape可被实例化 - 纯虚函数可以有定义(极少用),但声明处必须带
= 0,定义写在类外
派生类必须实现所有纯虚函数才能实例化
只要继承了抽象类,又没重写全部纯虚函数,派生类依然是抽象类。容易忽略的是:函数签名必须完全一致(包括 const、noexcept、引用限定符),否则不算重写。
比如基类是 virtual void render() const = 0;,子类写 void render() {}(缺 const)→ 编译失败,因为这是新函数,不是重写。
- 参数类型、返回类型、const 修饰、noexcept 状态都要严格匹配
- 使用
override关键字能提前捕获签名不匹配问题,强烈建议加上 - 如果不想立刻实现某个纯虚函数,可以让派生类也变成抽象类(不实现它)
抽象类可以有构造函数、成员变量和非纯虚函数
抽象类不是“空架子”,它可以像普通类一样拥有数据成员、构造函数、普通成员函数,甚至带实现的虚函数。它的限制仅在于“不能 new 出对象”,其他功能不受限。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
典型用法是把共用逻辑(如初始化、校验、模板方法)放进抽象基类,让子类专注实现差异部分。
- 构造函数常用于初始化公共状态,比如
Shape(int id) : id_(id) {} - 非纯虚函数可用于提供默认行为,比如
virtual bool valid() const { return id_ > 0; } - 析构函数应声明为
virtual(最好加= default或实现),否则通过基类指针 delete 派生对象会未定义行为
抽象类 vs 接口类:C++ 没有 interface 关键字,但可以模拟
C++ 没有 interface,但可以用“只含纯虚函数 + public 继承”的抽象类来模拟 Java/C# 中的接口语义。关键区别在于:抽象类可含状态和实现,接口类不应含数据成员或非纯虚函数。
实际项目中,是否允许含状态取决于设计意图:如果只是契约定义(如 Drawable、Serializable),就保持纯虚;如果需要共享资源或生命周期管理(如 ResourceHolder),就合理加入成员和实现。
- 纯接口风格:所有函数纯虚、无数据成员、析构函数为
virtual ~Interface() = default; - 混合风格:含保护成员变量、构造/析构逻辑、部分默认实现,适用于有共同基线行为的类族
- 多重继承时,优先用纯接口类组合,避免菱形继承歧义
抽象类真正的门槛不在语法,而在设计判断:哪些行为必须由子类决定,哪些可以下沉复用,以及是否真需要运行时多态而非模板或策略模式。写完 = 0 后,更该想清楚的是——谁来继承它、为什么不能用组合替代。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










