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

深入解析:从C++开始的编程生活(16)——继承

前言

本系列文章承接C语言的学习,需要有C语言的基础才能学会哦~
第16篇主要讲的是有关于C++的继承
C++已经进入进阶,加油!!

目录

前言

继承

普通类继承

语法

子类访问父类成员的访问限定符限制

继承类模板

基类与派生类之间的转换

继承的隐藏作用域

派生类的默认成员函数

构造函数

拷贝构造

析构函数

继承与友元

继承和静态成员

单继承、多继承和菱形继承

虚继承virtual

多继承的指针偏移

继承和组合


继承

是实现面向对象编程的复用代码的一个重要手段。

当两个类有重复的功能或函数时,就把这些重复功能创建为父类,让这两个类去继承父类。这样一来,这两个类只用写独自独特的成员函数,重复部分都复用父类的代码即可。

普通类继承

语法

//父类(基类)
class person
{
public:str _name;int _number;
}
//子类(派生类)
class Student: public person
{
public:string _class;
}

此处student类public方式继承于person类,student就也有父类的成员了。

子类访问父类成员的访问限定符限制
类成员/继承方式public继承protected继承private继承
基类的public成员派生类public成员派生类protected成员派生类private成员
基类的protected成员派生类protected成员派生类protected成员派生类private成员
基类的private成员派生类中不可见派生类中不可见派生类中不可见

①可父类成员在子类中的访问方式取决于谁的限定符限制更大。比如基类protected和子类private继承,private限制大,所以就能访问方式为private,此时可以访问基类的protected和public成员。
②父类的private成员,无论如何都无法被子类直接使用。只能靠调用父类的为被限制的函数进行访问。
③使用class则默认为private继承,使用struct则默认为public继承。

继承类模板

当基类是类模板时,需要指定类域。

因为模板是按需实例化,还未被使用的父类成员函数由于未实例化,无法被找到,编译会报错,所以要指明类域来避免这种错误。

同样的,如果父类有内部类,也要注意是否被实例化的问题。

基类与派生类之间的转换

①public继承的派生类对象可以赋值给基类的指针/引用。(也叫赋值兼容转换)

Student sobj;
Person *pp = &sobj;
Person &rp = sobj;

把sobj赋值给了Person类指针/引用,这时我们使用这些指针/引用时就不会访问到sobj的独有成员。

这种操作也叫做切片、切割。

②但是基类对象不可以赋值给派生类对象。

继承的隐藏作用域

若子类和父类有同名的成员,访问时默认优先访问最近类域中的成员,我们也可以自行指明类域来访问。

那么不访问的同名成员,就会被隐藏,这些同名的成员构成隐藏关系。

被隐藏的成员无法被使用。

class A
{
public:void fun(){cout << "Hi" << endl;}
};
class B : public A
{
public:void fun(int i){cout <<"int i" << endl;}
};

此处A类的fun被隐藏,若要使用A的fun函数,就要指定类域来使用。

派生类的默认成员函数

构造函数

派生类的默认构造,最好要自己写。对继承的父类成员,我们要用父类的构造函数进行构造。

class Person
{
public:Person(const char* name):_name(name){}
protected:string _name;
};
class Student : public Person
{
public:Student(int num, const char* address, const char* name):_num(num),_address(address),Person(name)//父类成员使用父类的构造。{}
protected:int _num;string _address;
};

父类的部分,我们把它们看作一个整体,统一走父类的构造函数来构造。

注意格式哦!

ps:若某类的默认构造为私有的,那么这个类将无法被继承。
或者被final修饰之后就不可以被继承了(关键词final在C++11支持)。

拷贝构造

一般使用默认生成的拷贝即可。同样的,父类的成员要调用父类的拷贝构造。默认生成的拷贝是浅拷贝,如果不能满足需要就要自己写一个深拷贝的拷贝构造。

要注意的是,子类的赋值运算符重载要用到父类的赋值运算符重载,父类的赋值运算符重载会被隐藏,需要指定类域来使用。

析构函数

一般用默认生成的析构即可。顺序是先析构子类,再析构父类。

当我们自己写析构函数的时候,要注意不用显示调用父类的析构时。
在默认情况下,父类的析构函数与子类的构成隐藏关系,这是规定,详细原因再有关多态的部分可以讲。

继承与友元

一句话概括,友元关系不可以继承。

继承和静态成员

一句话概括,父类和子类共用父类的静态成员

单继承、多继承和菱形继承

语法:

class Assistant:public Student,public Teacher

单继承:一个子类只有一个直接父类。


多继承:一个子类(C)有两个或以上的直接父类(A、B)。


菱形继承:某子类(D)间接多次继承同一个基类(A)。

此时因为D间接继承了两次父类A,所有会有两份父类A的成员,导致数据冗余。

多继承和菱形继承会造成数据冗余和二义性(若有同名变量可能会不发辨别是哪个类的变量,或者这个变量是哪个父类或者哪个子类的),即使二义性可以靠指定类域解决,但是数据冗余的问题无法解决。

虚继承virtual

用于解决菱形继承的二义性和数据冗余的问题。

用关键字virtual修饰菱形腰部的类(上图的B、C),编译时就只会保留一份数据。

了解即可,实际上最好不要使用多继承,即使使用多继承,也最好不要出现菱形继承的情况。

多继承的指针偏移

//D多继承于B1和B2
class B1 { public: int _b1;};
class B2 { public: int _b2;};
class D : public B1, public B2 { public: int _d;};
int main()
{D d;B1* p1 = &d;B2* p2 = &d;D* p3 = &d;return 0;
}

三个指针都用&d来赋值,但是p1 == p3 != p2。

可以用赋值兼容转换的切割来解释。
如图

p1和p2只能指向d继承父类的部分,p1指向B1部分,p2指向B2部分。而且,虽然p1 == p3但是两个指针的含义也是不同的,p1是对继承父类B1的切片,p3指向的是整个D。

继承和组合

继承是is-a的关系(如Student类继承于Person类,即Student is a Person)。
组合是has-a的关系(如Car类有Seat类的成员,即Car has a Seat)。

两者都对代码进行了复用,能够提高开发效率。
不同的是:

特性/复用方式继承(白箱复用)组合(黑箱复用)
可见性父类的成员对子类可见内部细节不可见
封装性破坏基类封装,派生类依赖基类实现保持类的封装,组合类依赖接口而非实现
耦合性高耦合低耦合

白箱和黑箱是相对于可见性而言的,白箱可见细节,黑箱不可见细节。

耦合性高的代码,每个部分环环相扣,如果某处出错或者进行修改,就会牵一发而动全身,这对代码的维护工作来说是不利的。

因此,实际应用中尽量使用组合,主要还是看类与类之间的关系。如果是更符合is-a关系,就用继承;如果更符合has-a关系,就用组合;如果两者都符合(比如链表和栈),那就优先使用组合。

❤~~本文完结!!感谢观看!!接下来更精彩!!欢迎来我博客做客~~❤

http://www.jsqmd.com/news/269072/

相关文章:

  • 13.6B参数铸就“世界模型”,美团LongCat-Video搭建5分钟原生视频生成,定义AI视频新标杆
  • 怎样免费在线把 HEIC 转为 JPG?无需安装软件,也不用上传照片
  • NodeJS生产环境发布流程
  • 2026年趋势全景图:AI重塑技术与翻译行业,这些变化你必须知道!
  • 人工智能标注工程师证书:超越标注之框,赋能技能跃迁
  • 考完PMP这几件事一定要做!
  • 竞品关键词实战指南:从挖掘到落地,抢占搜索流量高地
  • 深入解析Excel数组:从基础概念到高阶应用的完全指南
  • 参考文献怎么找:高效查找参考文献的实用方法与技巧
  • 数据(数据分析与大数据开发)的地位与作用?
  • Java程序员如何突击即将来临的春招?该做哪些技术储备? - 教程
  • 温州精密机械工厂10个SolidWorks设计画图共享一套SolidWorks
  • 连续3个月破10万!华为乾崑今年目标300万台
  • UI-TARS-desktop实战:用自然语言轻松操控电脑任务
  • 学术搜索引擎:高效获取学术资源的必备工具与使用指南
  • 导师严选 2026 毕业论文必备的8款AI论文软件测评
  • 环境监测仪器:认识十要素微气象仪
  • 【PFJSP问题】基于matlab自适应双种群协同鸡群算法ADPCCSO求解置换流水车间调度问题PFSP【含Matlab源码 14995期】
  • 氘可来昔替尼:全球首款 TYK2 变构抑制剂,改写银屑病治疗格局
  • 【优化形状】基于matlab非主导排序遗传算法的翼型形状优化【含Matlab源码 14992期】含报告
  • 智能体工作原理全解析:从环境感知到行动决策,收藏这篇就够了!
  • 横河 AQ6370E 光谱分析仪
  • 【数字信号去噪】基于matlab改进的灰狼算法和条件重初始化策略模型无主动噪声控制【含Matlab源码 15001期】
  • 邦芒解析:最难升职的六种职场人员
  • 58 同城 item_get - 获取详情数据接口对接全攻略:从入门到精通
  • 【2026年精选毕业设计:基于多模态识别的社区智能报修与设施巡检系统(含全套资料)】
  • 58 同城 item_search - 获取搜索数据接口对接全攻略:从入门到精通
  • 瞧瞧别人家的判空,那叫一个优雅!
  • 详细介绍:C#中常见集合都有哪些?
  • 网络安全毕设本科生方向集合