C++ 继承与多态(上)

我们今天主要讲一下继承^-^

一、什么是继承

1.概念

继承机制 是面向对象程序设计使代码 可以复用 的重要手段,它允许我们在保持原有类特性 的基础上进行扩展,增加方法(成员函数 )和属性(成员变量 ),这样产生新的类,叫做子类

父类(基类):被继承的类的统称

子类(派生类):继承父类、并拓展功能的类

2.核心作用

极大减少重复代码

形成清晰的类层结构

为多态打基础

二、语法及继承方式

1.语法

首先要有一个父类

其次子类:

class 子类名 :继承方式 父类名

{

//子类独有成员(函数或变量)

};

2.三种继承方式

2.1继承方式

public,protected,private

2.2继承规则

不难发现以下特点:

父类中的private的成员都在子类中不可见。

最终在子类中是什么成员为 min{ 父类成员 ,继承方式},两者的较小值

(public > protected < private)

注意:

1.如果不明确表明继承方式,class定义的子类就默认为private继承,struct定义的子类就默认为public继承。

2.实际运用中大部分使用public继承。

3.public继承的子类对象可以赋值父类的指针\对象\引用。("切片":寓意把子类中父类的那部分切出来赋值过去)

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

1.构造函数

子类的构造函数必须调用父类的构造函数初始化父类成员的那部分成员,如果父类没有默认构造函数,就在子类构造函数的初始化列表阶段显示调用。

2.拷贝构造函数

子类的拷贝构造函数必须调用父类的拷贝构造函数完成父类的拷贝初始化。

3.析构函数

子类的析构函数会在被调用完成后自动调用父类的析构函数清理父类成员。因为这样才能保证子类对象先清理子类成员再清理父类成员。

因为多态中一些场景需要构成重写,重写的条件之一就是函数名相同。那么编译器会对析构函数名进行特殊处理,处理成destrctor(),所以父类的析构函数不加virtual(下文会讲)的情况下,子类析构函数和父类析构函数构成隐藏关系。

4.其他内容

  1. 手动承载子类的operator=必须调用父类的operator=完成父类的复制,注意:子类的operator=隐藏(具体内容请看第四点^_^)了父类的operator=,所以显示调用父类的operator=时需指定作用域。

2.子类对象初始化先调用父类构造再调子类构造。

3.子类对象析构清理先调用子类的析构再调用父类的析构。

四、同名隐藏规则

子类中只要出现和父类同名 的成员(变量 / 函数 / 重载运算符),父类中所有同名重载版本,都会在子类作用域被全部隐藏;子类直接访问名字只会匹配自己的,想要访问父类必须指定作用域。 注意:只看名字 相同,不看参数返回值

区分:

**重载:**同一个类内,同名不同参数,编译器根据参数匹配;

**同名隐藏:**父子类之间,只要名字一样,不管参数,父类全藏,不在同一个作用域,不构成重载。

五、单继承/多继承/菱形继承

1.单继承

一个子类只继承一个父类

2.多继承

一个子类同时继承多个父类

3.virtual

virtual用于继承:虚继承(解决菱形继承数据冗余、二义性)

virtual可以让子类共用同一个实例,节省内存。

(这里我们先简单了解,多态时细讲。)

写法:

class A

{};

class B : virtual public A

{};

4.菱形继承

普通菱形两大问题:

数据冗余:F里面存两份 A的成员(B 带来一份、C 带来一份);

访问二义**:**不知道该访问谁

**解决办法:**加virtual

靠近公共祖宗(A)的那一层派生(B/C)加 virtual,子孙层不加。

消除冗余数据(核心作用):

不加 virtual:F 里两份 A(C 带来一份、D→B 带来一份 A 成员),内存重复占用;

加 virtual:整个 F 只保留 1 份 A,B、C、D、F 共用同一个 A 实例,节省内存。

消除访问二义性:(如果A里有一个成员变量a)

无 virtual:F.成员名编译报错,二义,必须F.B::a指定类域;

有 virtual:F.a直接访问,不存在二义。

六、继承和组合

1. 继承(is-a)

格式:class 子类 : public 父类

关系:是一个,如猫是动物。

特点:子类拥有父类全部成员,代码复用;耦合高;用于多态。

缺点:父类一改,子类全受影响。

2. 组合(has-a)

格式:类里定义别的类对象作为成员变量

比如:

class A

{};

class B

{

int n;

A a;

};

关系:包含有,如汽车有发动机。

特点:低耦合,只用对方功能,不继承成员;优先推荐。

七、继承的优缺点

1.优点

代码复用:子类直接复用父类已有成员与方法,不用重复编写相同代码,减少冗余。

在不修改父类源码前提下,派生类新增独有属性 / 函数。

多态实现基础:配合虚函数实现运行时多态,同一接口不同实现。

层次化管理:梳理类之间从属关系,逻辑清晰,符合现实事物分类。

2.缺点

高耦合:子类强依赖父类,父类代码改动会连锁影响所有派生类,破坏封装。

继承层级太深可读性变差:多层继承后代码溯源困难,调试复杂。

普通多继承易出现菱形继承,增大内存开销。

如果有不对的地方,感谢大佬指正^ ^

相关推荐
skywalk81631 小时前
我想基于kotti-py312 ,制作一个多中文编程语言的宣传网站,主要包括文档、playground 示例和学习 (Codearts制作)
开发语言·学习·编程
聆风吟º1 小时前
【C++11新章】列表初始化详解
开发语言·c++·列表初始化
alwaysrun1 小时前
C++之灵活易用的YAML解析库yaml-cpp
c++·后端·程序员
闪电悠米1 小时前
黑马点评-秒杀优化-04_lua_and_db_fallback
服务器·开发语言·网络·数据库·缓存·junit·lua
Shadow(⊙o⊙)1 小时前
进程间通信0.0-pipe()匿名管道,详细分析进程池调度队列执行逻辑,进程池模拟实现。
linux·运维·服务器·开发语言·c++
lcj25111 小时前
【list】【手撕 STL】List 容器全解析!迭代器 / 增删改查 / 去重排序,面试必背的核心考点!
c++·面试·list
指尖的爷1 小时前
C++头文件的作用
开发语言·c++
keykey6.1 小时前
反向传播与梯度下降:神经网络如何学习
开发语言·人工智能·深度学习·机器学习
Jun6261 小时前
QT(5)-第三方日志系统
开发语言·数据库·qt