设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间01 现在时间01 缓存数据 当你走完一段之后回头看,你会发现,那些真正能被记得的事真的是没有多少,真正无法忘记的人屈指可数,真正有趣的日子不过是那么一些,而真正需要害怕的也是寥寥无几。

当你走完一段之后回头看,你会发现,那些真正能被记得的事真的是没有多少,真正无法忘记的人屈指可数,真正有趣的日子不过是那么一些,而真正需要害怕的也是寥寥无几。

查看: 394|回复: 2

C++深入探究继承的概念与使用

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:234
  • 打卡月天数:0
  • 打卡总奖励:3400
  • 最近打卡:2025-11-26 04:35:40
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
403
主题
387
精华
0
金钱
4638
积分
864
注册时间
2023-1-4
最后登录
2025-11-26

发表于 2023-2-13 11:29:41 | 显示全部楼层 |阅读模式
1、概念及定义


1.1 概念

继承主要的工作就是-----共性抽取
具体地讲:
①继承机制是面向对象程序设计使代码可以复用的最重要的手段;
②允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样实现的类称为派生类/子类。基于实现该类的原有类称为基类/父类
③继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。(比如:animal—>dog---->kinds of dogs)
④继承是类层次设计的复用

1.2 定义
  1. 定义方式:class 派生类:继承方式 基类
复制代码
继承方式可以是
  1. public、protected、private
复制代码
三种,他们在继承基类时,所具有特性以及表现出的结果也有所不同,具体如下:
以public的方式继承基类
123025dya1upa9e8118p49.png

结论:
在public的继承方式下:
①父类中的成员变量的访问权限,到子类中不会发生改变
②父类中的私有访问权限的变量在子类中不可见(不能直接被访问)
问题:类在设计的时候,访问权限应该如何选择?
应该遵循以下3点原则:
123025fcavi27nnunizuzq.png

以protected的方式继承基类
123026lvlerqz3dvpddle4.png

结论:
在protected的继承方式下:
①基类中public修饰的 成员在子类中访问权限为protected
②基类中protected修饰的成员在子类中的访问权限依旧是protected
③父类中的private访问权限的变量在子类中不可见(不能直接被访问)
以private的方式继承基类
123026b4iw4epeb4ipkce4.png

结论:
在private的继承方式下:
①基类中public修饰的 成员在子类中访问权限为private
②基类中protected修饰的成员在子类中的访问权限为private
③父类中的private访问权限的变量在子类中不可见(不能直接被访问)
上面详细分析了每一种个情况,下面我们针对上面的结论进行汇总:
123026q1i3idrmjt3jglfr.png

注意:
1、基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
2、基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的
3、在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

2、class与struct的区别

主要有以下3点区别:
123027qdt4s64cc8upte8p.png


3、赋值兼容规则

前提:一定在public的继承方式下才满足
可以直接使用子类对象给父类对象赋值,反过来不行
这个很好理解,具体和可以通过两个方面理解:
①子类和父类的关系是is–a的关系,因此使用子类给父类赋值时可以的
②从对象模型来说。
对象模型可以简单理解为成员变量在内存中的布局情况;
123027x5fpmf0m56v5fjpu.png

可以使用基类的指针指向子类的对象,反过来不行
如果一定要指向,必须强转,不推荐,仅仅是能通过编译,但是在使用的时候可能会造成程序崩溃
分析如下:
123027bk9w9zt1eau2fye5.png

可以使用基类的引用去引用子类对象,反过来不行
引用在底层本质上就是使用指针实现的,因此它和指针的理解思路是一致的,这里就不再赘述。

4、继承中的作用域问题

明确:派生类和基类隶属于不同的作用域
那么,现在有这样一种情况:
基类和派生类中出现了同名的成员变量或成员方法。这种情况要如何去理解呢? 首先,他一定不是函数重载,因为函数重载的前提必须是在同一作用域。 其实它就是我们本模块要介绍的----同名隐藏(重定义)问题
基类和派生类中出现同名的成员时,会有如下问题的存在:
123028xjxa1k625ffh122q.png

那么,该如何解决呢?
只需要在访问的时候加上 基类名称和作用域限定符即可,这样做的目的是明确告诉编译器被调用成员所处的作用域
123028ozbnlxywsk0yefbl.png

建议:一般情况下,在继承体系中最好不要定义同名的成员

5、派生类(子类)的默认成员函数


5.1 构造函数

主要取决于基类的情况,分为两大类进行讨论:
基类没有显式定义任何构造函数
子类可以提供构造函数,也可以不提供构造函数 是否提供根据子类中完成的功能或者具体情况决定
基类显式定义了构造函数
①基类的构造函数是无参或者全缺省的
子类可以提供构造函数,也可以不提供构造函数
是否提供根据子类中完成的功能或者具体情况决定
②基类的构造函数是非默认构造函数
子类必须要定义自己的构造函数
在子类构造函数初始化列表位置显式调用基类的构造函数(完成从基类中继承下来的成员的初始化工作)
123028t7t8tui3op638iq8.png

基类和子类构造函数的调用先后顺序是怎样的?
把握一点:
创建那个类的对象,编译器就会调用这个类的构造函数
例如:创建子类对象,本质上调用的是子类的构造函数,但是在子类的构造函数的初始化列表处会调用基类的构造方法来初始化从基类继承下来的对象。然后再去执行子类构造函数的函数体。 因此,从结果上来看是基类对象的构造函数先执行完毕,子类构造函数后执行完毕。

5.2 拷贝构造函数

取决于基类的情况,主要分为两类:
基类的拷贝构造函数未定义
子类的拷贝构造函数可定义可不定义,根据子类的实际情况决定
基类的拷贝构造函数定义了
子类也需要定义拷贝构造函数,并且需要在子类的拷贝构造函数初始化列表的位置显式调用基类的拷贝构造函数
123028sy2ybjzllopycllo.png


5.3 赋值运算符重载

1.基类的赋值运算符重载未定义
子类可定义可不定义
2.基类的赋值运算符重载显式定义了
子类也需要定义,分为两个大的步骤:
①调用基类的赋值运算符重载给基类部分成员赋值base::operator= (d);
②给子类自己新增的部分进行赋值
注意:基类的operator= 与子类自己的 operator= 构成了同名隐藏,因此要加作用域限定符指定调用基类的operator=,否则默认调用子类自己的operator=,就会陷入无限递归
正确示范:
123029m8iwwwhxsiie8cyc.png

错误示范:
123029hxpcm4pdwuxd4wt2.png


5.4 析构函数

编译器将子类的析构函数编译完成之后,会自动在子类析构函数的最后一条语句之后插入一条调用基类析构函数的汇编语句call ~Base();!
123029bb81zc1jhhjshchb.png

问题:基类和子类析构函数调用先后顺序?
123029p80lnl41lkpn8p2k.png


6、基类中哪些成员被子类继承了


6.1 成员变量

普通成员变量,全部被继承!
这个我们在本文的1.2 定义这个模块已经全部验证!
静态成员变量也被继承了
注意:静态成员变量在整个继承体系中只有一份
验证:通过静态变量来记录创建对象的个数
  1. class Base
  2. {
  3. public:
  4.         Base(int a,int b)
  5.         {
  6.                 _a = a;
  7.                 _b = b;
  8.                 ++_count;
  9.         }
  10.         Base(const Base& b)
  11.         {
  12.                 _a = b._a;
  13.                 _b = b._b;
  14.                 ++_count;
  15.         }
  16.         Base& operator=(const Base& b)
  17.         {
  18.                 _a = b._a;
  19.                 _b = b._b;
  20.                 return *this;
  21.         }
  22.         ~Base()
  23.         {
  24.                 cout << "Base::~Base()" << endl;
  25.                 --_count;
  26.         }
  27. public:
  28.         int _a;
  29.         int _b;
  30.         static int _count;
  31. };
  32. int Base::_count = 0;
  33. class Derived : public Base
  34. {
  35. public:
  36.         Derived()
  37.                 :Base(1,2)
  38.         {
  39.         }
  40.         Derived(int a,int b,int c)
  41.                 :Base(a,b)
  42.                 , _c(c)
  43.         {}
  44.         Derived(const Derived& d)
  45.                 :Base(d)
  46.         {
  47.                 _c = d._c;
  48.         }
  49.         Derived& operator=(const Derived& d)
  50.         {
  51.                 Base::operator=(d);
  52.                 _c = d._c;
  53.                 return *this;
  54.         }
  55.         ~Derived()
  56.         {
  57.                 cout << "Derived::~Derived()" << endl;
  58.         }
  59. public:
  60.         int _c;
  61. };
  62. void Test()
  63. {
  64.         cout << &Base::_count << endl;
  65.         cout << &Derived::_count << endl;
  66. }
复制代码
123030eh0oq6gqgsshbtj1.png


6.2 成员方法

普通成员方法,被子类继承了。
前面的代码均有体现,这里不再验证~
静态成员方法—也被子类继承了
验证:
123030ebkk02wezk0e70c0.png


7、友元函数被继承了吗

明确:友元函数不是类的成员函数,他只是在一个类中进行声明,目的是打破类的封装性去访问原本外部不可访问的成员。
这个问题很好测试,我们只需要为子类提供一个友元函数去访问父类中的protected访问权限的成员变量。让一个子类继承自父类,然后测试在父类中声明的友元函数是否能够访问子类中的protected/private成员变量即可!
如果可以访问,那就说明 友元函数也会被继承下来。
如果不可以访问,那就说明友元函数不会被继承下来
直接上例子:
123030srgy32rddrx0d80k.png

Test函数测试结果:
123031vremslyfk9ljzzmk.png

结论:友元函数不能被继承!
本篇文章到这里就结束了,感觉有所帮助的读友,可以转发分享给身边的朋友并留下你们的足迹!
下篇我们讲讲C++中一些不同的继承体系~,我们下篇再见!
到此这篇关于C++深入探究继承的概念与使用的文章就介绍到这了,更多相关C++继承内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:无名新人
  • 打卡总天数:1
  • 打卡月天数:0
  • 打卡总奖励:17
  • 最近打卡:2025-03-31 06:59:42
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
32
积分
6
注册时间
2024-8-27
最后登录
2025-3-31

发表于 2025-4-7 14:45:49 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
11
积分
2
注册时间
2024-11-27
最后登录
2024-11-27

发表于 4 天前 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表