c++中“接口类”是只含公有纯虚函数、无数据成员、且含虚析构函数的抽象基类;如drawable类,必须声明virtual ~drawable() = default; 所有函数纯虚且public,不可有数据成员或非虚析构。

什么是C++里的“接口类”
C++没有像Java或C#那样的interface关键字,所谓“接口类”是程序员约定俗成的说法:一个只含纯虚函数、无数据成员、无构造/析构实现(或仅有虚析构)的抽象基类。它不负责实现逻辑,只定义行为契约。
关键判断:只要类中至少有一个virtual void func() = 0;,它就是抽象类;若全部函数都是纯虚、且不含非静态数据成员,就可视为接口类。
怎么声明一个干净的接口类
核心是两点:所有成员函数必须是公有纯虚函数,且显式提供虚析构函数——否则通过基类指针删除派生对象时会未定义行为。
class Drawable {
public:
virtual ~Drawable() = default; // 必须!即使空实现也得是 virtual
virtual void draw() const = 0;
virtual int width() const = 0;
virtual int height() const = 0;
};
注意:
- 不要写
protected:或private:成员,接口类不该封装状态 - 不要加任何数据成员(
int x;、std::string name;等),否则就不是纯粹接口 - 析构函数必须是
virtual,哪怕用= default,否则多态销毁会崩
继承并实现接口类时常见翻车点
派生类必须实现所有纯虚函数,否则自己也会变成抽象类,无法实例化。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
class Circle : public Drawable {
public:
void draw() const override { /* OK */ }
int width() const override { return m_diameter; }
// ❌ 忘了实现 height() → Circle 仍是抽象类,Circle c; 编译失败
private:
int m_diameter;
};
容易踩的坑:
- 忘记加
override关键字,导致函数签名微小不匹配(比如const漏写)却没报错,实际没覆盖 - 派生类析构函数不是
public或没声明为virtual(虽然不强制,但建议保持一致性) - 在接口里加了默认实现(
virtual void f() { }),这会让它偏离“纯接口”语义,调用方可能误以为可不重写
要不要用final或noexcept修饰接口函数
可以,但要看场景。加noexcept属于强契约:表示所有实现都承诺不抛异常。一旦某个实现抛了,程序直接std::terminate。
virtual void draw() const noexcept = 0;
使用建议:
- 若业务上绝对不允许某操作失败(如嵌入式渲染),加
noexcept能提前暴露问题 - 接口函数一般不加
final——那会阻止进一步派生,违背接口可扩展初衷 - 参数类型尽量用引用或
const值,避免值传递引发意外拷贝(尤其对大对象)
最常被忽略的是虚析构函数的必要性,以及把“能编译通过”当成“正确实现了接口”——运行时行为是否符合契约,还得靠测试和约定。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










