C++ 纯虚函数怎么定义 C++抽象类与接口规范讲解【架构】

发布时间 - 2026-01-27 00:00:00    点击率:
纯虚函数必须声明为virtual void f() = 0且无函数体;含纯虚函数的类为抽象类,不可实例化但可定义指针/引用;接口类应仅含public纯虚函数、无数据成员和非纯虚函数;多重继承时各基类纯虚函数须分别显式实现。

纯虚函数的定义语法必须带 = 0

纯虚函数不是“没实现的虚函数”,而是**语法上强制要求子类重写**的虚函数。它的定义必须在声明末尾写 = 0,且不能有函数体(哪怕空花括号也不行):

class Shape {
public:
    virtual double area() const = 0;  // ✅ 正确:= 0,无实现
    virtual void draw() = 0;         // ✅ 同样合法,const 不是必需的
    virtual void init() = 0 {}       // ❌ 错误:写了 {} 就不能再写 = 0
};

常见错误是把普通虚函数和纯虚函数混淆——比如只写 virtual void f(); 而不加 = 0,这仍是可实例化的虚函数,不会让类变成抽象类。

抽象类无法实例化,但可以定义指针和引用

只要类中至少有一个纯虚函数,它就是抽象类,new Shape()Shape s; 都会编译失败,报错类似:error: cannot declare variable 's' to be of abstract type 'Shape'

但你完全可以:

  • Shape* 指向派生类对象(多态基础)
  • const Shape& 绑定临时对象或子类实例
  • 作为函数参数或返回类型(如工厂函数返回 std::unique_ptr

注意:抽象类的构造函数/析构函数仍会被调用,所以析构函数建议也声明为 virtual ~Shape() = default;

否则通过基类指针 delete 可能导致未定义行为。

接口类(Interface)要避免数据成员和非纯虚函数

C++ 没有 interface 关键字,所谓“接口类”是靠约定形成的规范:只含 public 纯虚函数、无数据成员、无构造函数实现、析构函数为纯虚或虚默认。

典型反例:

class BadInterface {
protected:
    int id_;                    // ❌ 数据成员破坏接口纯洁性
public:
    virtual void run() = 0;
    virtual void stop() { }     // ❌ 提供默认实现,就不是纯粹的契约了
};

更干净的写法:

class Drawable {
public:
    virtual ~Drawable() = default;
    virtual void draw() const = 0;
    virtual void update() = 0;
};

如果真需要默认行为,应由派生类自己用组合或模板方式复用,而不是在接口里塞实现。

多重继承下纯虚函数的实现容易漏覆盖

当一个类从多个抽象基类继承时,每个纯虚函数都必须被显式实现,哪怕签名完全一样也不能“自动继承”:

class A { public: virtual void f() = 0; };
class B { public: virtual void f() = 0; };
class C : public A, public B {
public:
    void f() override { }  // ✅ 必须写,否则 C 仍是抽象类
};

若遗漏,编译器不会帮你合并或提示“已实现”,只会继续报错 C is an abstract class。更隐蔽的情况是签名看似相同但 const/volatile 限定符不一致,比如 A::f()B::f() const 是两个不同函数,C 必须分别实现。

这种细节在大型模块解耦或跨团队接口对接时特别容易出问题,建议配合静态分析工具(如 clang-tidy 的 cppcoreguidelines-interfaces-global-init 类规则)做检查。


# 工具  # c++  # 接口对接  # 架构  # 多态  # 子类  # 构造函数  # 析构函数  # Error  # const  # void  # volatile  # 指针  # 继承  # 虚函数  # 纯虚函数  # 接口  # class  # public  # 多重继承  # Interface  # delete  # 对象  # default  # 抽象类  # 仍是  # 报错  # 是在  # 派生类  # 多个  # 无数据  # 帮你  # 而不 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在腾讯云免费申请建站?  如何快速搭建FTP站点实现文件共享?  Internet Explorer官网直接进入 IE浏览器在线体验版网址  如何安全更换建站之星模板并保留数据?  做企业网站制作流程,企业网站制作基本流程有哪些?  Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】  JavaScript Ajax实现异步通信  详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  Laravel PHP版本要求一览_Laravel各版本环境要求对照  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】  详解vue.js组件化开发实践  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  googleplay官方入口在哪里_Google Play官方商店快速入口指南  如何快速使用云服务器搭建个人网站?  如何快速搭建高效香港服务器网站?  Laravel如何为API编写文档_Laravel API文档生成与维护方法  电商网站制作价格怎么算,网上拍卖流程以及规则?  如何用景安虚拟主机手机版绑定域名建站?  高端建站如何打造兼具美学与转化的品牌官网?  php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  Laravel怎么导出Excel文件_Laravel Excel插件使用教程  如何用美橙互联一键搭建多站合一网站?  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  Android自定义listview布局实现上拉加载下拉刷新功能  Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性  Java类加载基本过程详细介绍  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  如何快速建站并高效导出源代码?  历史网站制作软件,华为如何找回被删除的网站?  网页设计与网站制作内容,怎样注册网站?  Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives  Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧  Python高阶函数应用_函数作为参数说明【指导】  Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  js实现获取鼠标当前的位置  如何在IIS7中新建站点?详细步骤解析  如何在IIS中新建站点并解决端口绑定冲突?  如何在香港服务器上快速搭建免备案网站?  英语简历制作免费网站推荐,如何将简历翻译成英文?  Laravel集合Collection怎么用_Laravel集合常用函数详解  教你用AI润色文章,让你的文字表达更专业  Laravel如何使用Blade组件和插槽?(Component代码示例)  Python数据仓库与ETL构建实战_Airflow调度流程详解  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤