当前位置: 首页 > news >正文

《你真的了解C++吗》No.029:抽象类的构造与析构——不存在的实体,存在的基石

《你真的了解C++吗》No.029:抽象类的构造与析构——不存在的实体,存在的基石

导言:一个逻辑悖论?

在 No.022 中我们聊过,抽象类(包含纯虚函数的类)是无法实例化的。如果你写AbstractShape s;,编译器会直接把你挡在门外。

既然这种类永远不会在内存中独立存在,很多人就会产生疑问:它还需要构造函数和析构函数吗?答案是:不仅需要,而且它们在对象“拼图”的完成中起着不可替代的作用。


一、 物理本质:派生类是个“夹心饼干”

要理解为什么抽象类需要构造函数,必须看清派生类对象的内存物理排布。

当你创建一个Circle对象(继承自抽象类Shape)时,在内存中:

  1. 底层:是Shape的成员变量和虚指针。
  2. 上层:是Circle特有的成员变量。

构造规则
C++ 规定,任何对象的初始化必须遵循**“先祖后辈”**的顺序。当Circle构造时,它必须首先调用Shape的构造函数来初始化基类那部分的成员。即使Shape是抽象的,它依然拥有需要被初始化的数据(比如colorvptr)。


二、 抽象类构造函数的“幕后黑手”

抽象类的构造函数通常被声明为protected。这样做有两个原因:

  1. 限制访问:既然外界不能实例化它,暴露public构造函数没有意义。
  2. 强制协作:它明确告诉开发者,这个构造函数是专门给子类在初始化列表(Member Initialization List)里调用的。
classShape{// 抽象类protected:intid;Shape(inti):id(i){}// 依然可以有逻辑public:virtualvoiddraw()=0;};classCircle:publicShape{public:Circle(inti):Shape(i){}// 子类必须显式调用基类构造};

三、 析构函数:抽象类最容易犯错的地方

这是本章最核心的警示:抽象类的析构函数绝不能省略,且必须是虚的(virtual)。

即使一个类是抽象的,当通过基类指针删除子类对象时,如果析构函数不是虚的,就会发生内存泄漏:

Shape*p=newCircle();deletep;// 如果 ~Shape() 不是虚的,Circle 的析构函数永远不会被调用

纯虚析构函数的特殊性
你甚至可以把析构函数声明为纯虚的,来强迫这个类变成抽象类:
virtual ~Shape() = 0;
但请记住,你必须为这个纯虚析构函数提供函数体Shape::~Shape() {}),因为子类析构时,最终一定会向上调用基类的析构函数。如果没有定义,链接器会报错。


四、 编译器生成的“隐形代码”

即使你没在抽象类里写构造函数,编译器也会为你生成一个默认的。
这个隐形函数最重要的任务不是初始化变量,而是初始化虚指针(vptr)

  • Shape的构造过程中,vptr会被暂时指向Shape的虚表。
  • 随后在Circle的构造过程中,vptr才会被重写为指向Circle的虚表。
    这个“vptr 演变”的过程,决定了我们在下一章(No.030)要讨论的那个致命陷阱。

总结:抽象类不“空”

  • 构造函数:是为了确保派生类中属于基类的那部分内存被正确初始化。
  • 析构函数:是为了确保通过多态删除对象时,清理链条不会断裂。
  • 抽象类是一个半成品,构造函数则是组装这个半成品不可或缺的工序。
http://www.jsqmd.com/news/311897/

相关文章:

  • 三大优选发育迟缓康复训练机构:以专业之力,护航特殊儿童成长
  • 成都3家硬核自闭症康复机构盘点|家长收藏,早期干预少走弯路
  • 2026自闭症康复机构选购指南:权威榜单+避坑攻略,家长别再踩雷
  • 看2026靠谱AI智能无损选果机生产厂家排行,选优质设备,分选机/无损分选机/西瓜选果机,AI智能无损选果机制造商推荐榜
  • 2026年水果分选机选购指南,这些生产商值得一看!无损测糖选果机/智能水果分选机/分选机,水果分选机源头厂家有哪些
  • COSMO一代星(CSK)二代星(CSG)重采样、配准
  • 天津4家优质自闭症机构排名!专业度+口碑双在线,家长收藏不踩坑
  • 自闭症机构怎么选不踩坑?2026权威推荐+避坑指南,家长收藏!
  • 星宝干预不迷路!自闭症康复机构及方法指南
  • 深入解析 virsh console:KVM虚拟化中的文本控制台魔法
  • 多店版二手车小程序源码系统,每家门店拥有独立的后台管理模块
  • 【第三方软件测试测评机构:使用LoadRunner测试HTTPS/SSL协议应用的配置和证书处理 】
  • 3.10 Helm包管理实战:复杂应用模板化部署完整教程
  • 3.11 CronJob定时任务实战:Kubernetes原生定时任务调度方案
  • 3.12 Service服务发现机制:ClusterIP、NodePort、LoadBalancer三种类型对比
  • 3.10 DaemonSet和Job控制器:节点守护进程与批处理任务完整实战
  • 救命神器10个一键生成论文工具,研究生高效写作必备!
  • 人工智能课程【数据库模块】01.数据库基础
  • 人工智能课程【数据库模块】01.数据库基础-在Ubuntu 24.04.3 LTS上安装MySQL 8并配置utf8mb4字符集
  • 人工智能课程【数据库模块】01.数据库基础-在Ubuntu 24.04.3 LTS上安装并配置MariaDB(端口3307,独立数据目录)
  • 信奥赛C++提高组csp-s之数位DP详细讲解
  • 信奥赛C++提高组csp-s之状压DP详解及编程实例
  • 睡眠监测传感器哪家好?五大核心品牌技术解析
  • 基于Gerchberg-Saxton(GS)算法实现衍射光学元件(DOE)设计
  • 2026中国木门十大品牌排行榜:行业品质之选推荐
  • ALSOLIFE靠谱吗?星娃家长必看:科研、师资、性价比三重硬核测评
  • ALSOLIFE深度解析:给特殊儿童家庭的专业干预新选择
  • 个人健康系统|健康管理|基于java+Android+微信小程序的个人健康高效的平台设计与实现(源码+数据库+文档)
  • ALSOLIFE科学吗?深度拆解:这家自闭症干预机构的硬核实力与专业底色
  • 2026尼龙回收市场:这些厂家值得一试,市场技术好的尼龙回收生产厂家净缘再生满足多元需求