C++继承

本文详细阐述了继承在面向对象编程中的概念、定义,包括访问限定符的应用、基类和派生类对象的转换规则,以及继承与友元、静态成员的关系。还讨论了复杂菱形继承和解决其问题的方法,强调了正确处理继承中的构造函数、析构函数和默认成员函数的重要性。
摘要由CSDN通过智能技术生成


1.前言

继承? 继承老爸的财产。

目录

1.前言

2.继承的概念及定义

1.1继承的概念

1.2 继承定义

1.2.2继承关系和访问限定符

1.2.3继承基类成员访问方式的变化

3.基类和派生类对象赋值转换

​编辑3.继承中的作用域

4.派生类的默认成员函数

5.继承与友元

6. 继承与静态成员

7.复杂的菱形继承及菱形虚拟继承


本节目标:

1. 继承的概念及定义
2. 基类和派生类对象赋值转换
3. 继承中的作用域
4. 派生类的默认成员函数
5. 继承与友元
6.继承与静态成员

2.继承的概念及定义

1.1继承的概念

继承 (inheritance) 机制是面向对象程序设计 使代码可以复用 的最重要的手段,它允许程序员在
持原有类特性的基础上进行扩展 ,增加功能,这样产生新的类,称派生类。继承 呈现了面向对象
程序设计的层次结构 ,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,
承是类设计层次的复用
如果你还是不明白 ,我举个例子你明白了。 世界上有一种高级生物叫做人类, 而人类又可以细分成三种 男人 女人 人妖 但是这三种人他们都有一些共同的属性 列如:年龄 身高 体重 
身份证号码  姓名 等等。但是他们又有不同属性 列如 职业 天赋 等等。这世界有太多的职业的每个职业我们定义出来 那就会有很多重复代码(年龄身高.....)
这时我们就可以把共同属性抽象出来描述成一个类。
请看下图
学号只有学生才会有 这时候我们在继承 person这个类成员。                                                              

通过继承我们就得到了person类的保护成员。

下面我们看到 Person 是父类,也称作基类。 Student 是子类,也称作派生类。

1.2 继承定义

1.2.2继承关系和访问限定符

1.2.3继承基类成员访问方式的变化

总结:
1. 基类 private 成员在派生类中无论以什么方式继承都是不可见的。这里的 不可见是指基类的私 有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面 都不能去访问它
2. 基类 private 成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在
派生类中能访问,就定义为 protected 可以看出保护成员限定符是因继承才出现的
3. 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他 成员在子类的访问方式 == Min( 成员在基类的访问限定符,继承方式 ) public > protected
> private
4. 使用关键字 class 时默认的继承方式是 private ,使用 struct 时默认的继承方式是 public 不过
最好显示的写出继承方式
5. 在实际运用中一般使用都是 public 继承,几乎很少使用 protetced/private 继承 ,也不提倡
使用 protetced/private 继承,因为 protetced/private 继承下来的成员都只能在派生类的类里
面使用,实际中扩展维护性不强。

3.基类和派生类对象赋值转换

•派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用 。这里有个形象的说法叫切片
或者切割。寓意把派生类中父类那部分切来赋值过去。
•基类对象不能赋值给派生类对象。
•基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类
的指针是指向派生类对象时才是安全的。

3.继承中的作用域

那如果我非要访问父类的同名成员怎么办? 简单

结论:

1. 在继承体系中 基类 派生类 都有 独立的作用域
2. 子类和父类中有同名成员, 子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,
也叫重定义。 (在子类成员函数中,可以 使用 基类 :: 基类成员 显示访问
3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。
4. 注意在实际中在 继承体系里 面最好 不要定义同名的成员

4.派生类的默认成员函数

请看下图

如果子类要初始化,要初始化父类的成员 不用person::(参数)直接 父名(参数)

同时也调用了析构函数 这里就不再过多解释构造函数和析构函数了,有疑问的可以去看之前的博客类和对象

拷贝构造也是一样

 下面再看赋值重载 子类和子类赋值重载我就不说了,和前面3个默认函数一样的 主要讲讲子类赋值给父类

再看析构函数 根据前面3个函数来说 子类析构函数要加父类析构函数吗?

从结果来看 父类的析构函数多调用了一次 ,这样肯定有问题 如果是自定义类型有指针的情况话程序就崩溃了。

正确的做法看下图

子类的析构函数不用加 父类的析构函数 原因多态的时候再说。

总结:
1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认
的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
3. 派生类的 operator= 必须要调用基类的 operator= 完成基类的复制。
4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能
保证派生类对象先清理派生类成员再清理基类成员的顺序。
5. 派生类对象初始化先调用基类构造再调派生类构造。
6. 派生类对象析构清理先调用派生类析构再调基类的析构

5.继承与友元

先说结论:

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员

解决方法 在子类中 再次声明友元函数

6. 继承与静态成员

先说结论:

基类定义了 static 静态成员,则整个继承体系里面只有一个这样的成员 。无论派生出多少个子
类,都只有一个 static 成员实例

7.复杂的菱形继承及菱形虚拟继承

这种为单继承

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。
Assistant 的对象中 Person 成员会有两份。
二义性好解决 类名加域限定符 就可以解决
数据冗余如何解决:用虚函数解决, 在多态的时候再细讲 。
关注我带你学习更多C++知识
  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值