news 2026/7/14 13:41:40

C++继承核心:默认成员函数详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++继承核心:默认成员函数详解

好的,我们来系统地学习C++中继承的核心概念,特别是关于默认成员函数的行为。


一、 继承的基本概念

  1. 什么是继承?

    • 继承是面向对象编程(OOP)的重要特性之一。
    • 它允许我们定义一个新的类(称为派生类子类),基于一个已经存在的类(称为基类父类)。
    • 派生类会“继承”基类的成员(数据成员和成员函数),并可以添加自己的新成员,或者重新定义(覆盖)继承来的成员函数。
  2. 为什么使用继承?

    • 代码复用:避免重复编写基类中已有的代码。
    • 层次化建模:反映现实世界中事物之间的“是一种(is-a)”关系(例如:Student是一种Person)。
    • 实现多态(通过虚函数):允许通过基类指针或引用来操作派生类对象。
  3. 继承类型

    • 公有继承class Derived : public Base { ... };
      • 基类的public成员在派生类中保持public
      • 基类的protected成员在派生类中保持protected
      • 基类的private成员在派生类中不可直接访问(需要通过基类的public/protected成员函数间接访问)。
      • 体现了“是一种”关系。
    • 保护继承class Derived : protected Base { ... };
      • 基类的publicprotected成员在派生类中都变为protected
      • 基类的private成员不可直接访问。
    • 私有继承class Derived : private Base { ... };
      • 基类的publicprotected成员在派生类中都变为private
      • 基类的private成员不可直接访问。
      • 体现了“由...实现”的关系,较少使用。

二、 访问控制与继承

  • 基类成员的访问权限(public,protected,private) 决定了它们在基类内部的可见性。
  • 继承方式(public,protected,private) 决定了基类成员在派生类内部最低访问级别
    • 基类的public成员在派生类中的访问权限 <= 继承方式指定的权限。
    • 基类的protected成员在派生类中的访问权限 <= 继承方式指定的权限。
    • 基类的private成员永远不能在派生类内部直接访问(无论何种继承方式)。
  • 派生类对象对基类成员的访问:
    • 只能访问派生类内部可见的基类成员(即经过继承方式调整后,在派生类中是public的成员)。
    • 派生类对象不能直接访问基类的protectedprivate成员(即使它们在派生类内部是可见的protected)。

三、 继承中的默认成员函数

当派生类被创建、销毁、赋值时,其默认的构造函数、析构函数、拷贝构造函数和赋值运算符的行为与基类紧密相关。

  1. 构造函数

    • 派生类对象的构造构造其直接基类部分(如果有多个直接基类,按照声明顺序构造)。
    • 然后按照声明顺序构造派生类自己的数据成员。
    • 规则
      • 派生类的构造函数默认会调用基类的默认构造函数(无参构造函数)。
      • 如果基类没有默认构造函数,或者你想调用基类的特定构造函数(带参数的),必须在派生类构造函数的初始化列表中显式调用基类构造函数。
    class Base { public: Base(int x) { /* ... */ } // 基类没有默认构造函数 }; class Derived : public Base { public: // 错误!默认会调用 Base(),但 Base 没有默认构造函数 // Derived() { ... } // 正确:在初始化列表中显式调用 Base(int) Derived(int y) : Base(y * 2) { ... } };
  2. 析构函数

    • 派生类对象的析构顺序与构造顺序相反
      • 首先执行派生类自己的析构函数体。
      • 然后按照声明相反的顺序销毁派生类自己的数据成员。
      • 最后按照继承树从底向上的顺序(即派生类析构后)调用其直接基类的析构函数。
    • 规则
      • 基类的析构函数会被自动调用
      • 如果基类的析构函数是虚函数,那么通过基类指针删除派生类对象时,会正确调用派生类的析构函数(这是良好实践!通常将基类析构函数声明为virtual)。
      • 如果基类析构函数不是虚函数,通过基类指针删除派生类对象会导致未定义行为(通常只调用了基类的析构函数,派生类部分未被正确销毁)。
  3. 拷贝构造函数

    • 当用一个派生类对象初始化另一个派生类对象时(如Derived d2 = d1;)。
    • 默认行为:派生类的默认拷贝构造函数会:
      • 调用基类的拷贝构造函数来初始化派生类对象中的基类子对象
      • 然后对派生类自己的成员进行值拷贝(如果成员是类类型,调用其拷贝构造函数)。
    • 自定义:如果你为派生类定义了拷贝构造函数,必须在初始化列表中显式调用基类的拷贝构造函数(或其它合适的基类构造函数),否则基类部分会调用默认构造函数。
    class Derived : public Base { public: // 默认拷贝构造函数大致等价于: // Derived(const Derived& other) : Base(other) { /* 拷贝成员 */ } // 自定义拷贝构造函数 Derived(const Derived& other) : Base(other) // 显式调用基类拷贝构造,传递派生类引用给基类引用 , /* 初始化派生类成员 */ { // ... } };
  4. 拷贝赋值运算符

    • 当将一个派生类对象赋值给另一个派生类对象时(如d2 = d1;)。
    • 默认行为:派生类的默认拷贝赋值运算符会:
      • 调用基类的拷贝赋值运算符来赋值派生类对象中的基类子对象
      • 然后对派生类自己的成员进行赋值(如果成员是类类型,调用其拷贝赋值运算符)。
    • 自定义:如果你为派生类定义了拷贝赋值运算符,必须显式调用基类的拷贝赋值运算符(通常通过作用域解析运算符::)。
    class Derived : public Base { public: // 默认拷贝赋值运算符大致等价于: // Derived& operator=(const Derived& other) { // Base::operator=(other); // 调用基类的赋值 // /* 赋值派生类成员 */ // return *this; // } // 自定义拷贝赋值运算符 Derived& operator=(const Derived& other) { if (this != &other) { Base::operator=(other); // 显式调用基类赋值 // ... 赋值派生类自己的成员,处理自赋值 ... } return *this; } };

四、 总结:类复用的核心逻辑

  • 继承是复用基类代码和接口的主要机制。
  • 理解访问控制继承方式是正确使用继承的基础。
  • 默认成员函数在继承体系中的行为规则确保了对象构造、析构、拷贝和赋值的正确性:
    • 构造:先基类,后派生类成员。
    • 析构:先派生类成员和析构函数体,后基类(与构造相反)。
    • 拷贝构造/赋值:需要显式或隐式处理基类子对象的拷贝/赋值。
  • 为基类声明虚析构函数是安全使用多态(通过基类指针操作派生类)的关键。

通过掌握这些基础概念和默认成员函数的行为,你就能更好地利用C++的继承机制来实现代码的复用和扩展。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 13:41:39

探索COMSOL等离子共振结构超材料完美吸收体的多波段高吸收率

COMSOL等离子共振结构超材料完美吸收体的多波段高吸收率。 研究宽谱和窄谱吸收的小伙伴可以联系哟。嘿&#xff0c;各位科研爱好者&#xff01;今天咱们来聊聊COMSOL等离子共振结构超材料完美吸收体那超厉害的多波段高吸收率。在光学和电磁学领域&#xff0c;超材料一直是研究的…

作者头像 李华
网站建设 2026/7/14 13:41:42

LightOnOCR-2-1B OCR模型微调指南:LoRA适配器训练+领域数据增强技巧

LightOnOCR-2-1B OCR模型微调指南&#xff1a;LoRA适配器训练领域数据增强技巧 1. 为什么需要微调OCR模型&#xff1f; 你可能已经体验过LightOnOCR-2-1B的基础能力&#xff0c;这个10亿参数的多语言OCR模型确实很强大&#xff0c;支持中英日法等11种语言。但在实际业务中&am…

作者头像 李华
网站建设 2026/7/14 13:41:41

FatMouse‘s Speed(dp模版2 最长上升子序列

题源 这是一题最长上升子序列的变种&#xff0c;首先要满足两个条件&#xff0c;体重递增&#xff0c;速度递减的子序列 体重递增采用结构体排序 速度递减&#xff0c;采用dp状态转移&#xff0c;记录路径采用记录前驱的方式后reverse可以满足 #include<bits/stdc.h> u…

作者头像 李华
网站建设 2026/7/14 13:41:57

基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的字母数字识别检测系统(DeepSeek智能分析+web交互界面+前后端分离+YOLO数据)

摘要 本项目设计并实现了一个集成了前沿目标检测技术与现代Web开发框架的智能化字母数字识别与检测系统。系统核心采用目前YOLO系列的最新及高性能版本&#xff08;包括YOLOv8、YOLOv10、YOLOv11和YOLOv12&#xff09;&#xff0c;构建了一个鲁棒性强的多字符识别模型&#xf…

作者头像 李华
网站建设 2026/7/14 13:41:58

若依数据权限深度解析:从@DataScope注解到SQL拼接的全链路追踪

若依数据权限架构解密&#xff1a;从注解驱动到动态SQL的工程化实践 在当今企业级应用开发中&#xff0c;数据权限控制是保障业务安全的核心环节。若依框架通过精巧的AOP设计与MyBatis深度整合&#xff0c;构建了一套声明式的数据权限解决方案。本文将带您深入DataScopeAspect切…

作者头像 李华