C++面向对象三大特性:封装,继承,多态。
C++认为万事万物皆是对象,对象有其属性和行为。具有相同性质的对象可以统称为类。
封装(面向对象三大特性之一)
意义:
将属性和行为作为一个整体,表现生活中的事物。
将属性和行为加以权限控制
意义1:在设计类的时候,将属性和行为写在一起,表现事物。
语法:class 类名{访问权限 : 属性/行为};
如下例子:
意义2:访问权限有三种:
1:public 公共权限 ( 类内可以访问,类外也可以)
2:protected 保护权限 (类内可以访问,类外不可以)儿子可以访问父亲中的保护内容
3:private 私有权限 ( 类内可以访问,类外不可以)儿子不可以访问父亲私有的内容
例子:
C++中 class与struct的区别
区别:默认访问权限不同。
class默认为私有,struct默认为公共。
例子:
成员属性设置为私有
优点:
1:可以控制读写权限
2:对于写权限,我们可以检测数据的有效性
例子
案例一:立方体类
设计一个立方体类,求面积和体积,用全局函数和成员函数来判断两个立方体是否相等。
案例二 点和圆关系案例
代码:
改良:
核心:在类中可以让另一个类作为本类中的成员存在
核心:分文件写
主函数:
Drop.cpp
Drop.h
Round.cpp
Round.h
继承(面向对象三大特性之一)
继承是面向对象与类之间存在的特殊关系
当下级的成员拥有继承的技术,减少重复代码
继承的基本语法:class子类:继承方式:父类
例如我们看到很多网站,都有相同公共的头部,公共的底部,甚至公共的左侧列表,只有中心内容不同。
接下来我们分别利用普通写法和继承的写法来实现网页中的内容,看一下继承存在的意义以及好处。
案例:1
2
3
补充:
继承语法:class子类:继承方式:父类
子类称派生类 父类称基类
派生类中的成员,包含两大部分:一类是从基类继承过来的,一类是自己增加的成员 从基类继承过来的表现共享性,而新增的成员体现其个性
继承的继承方式
继承方式:
继承的语法:class 子类:继承方式 父类
继承的三种方式:公共继承 保护继承 私有继承
案例
继承中的对象模型
问题:从父类继承过来的成员,那些属于子类对象中?
利用开发人员命令提示工具查看对象模型
跳转盘符 D:
跳转文件路径 cd具体路径下
查看命名:cl /d1 reportSingleClassLayout类名 文件名
继承中构造与析构的顺序
子类继承父类后,当创建子类对象,也会调用父类的构造函数
问题:父类和子类的构造和析构顺序是谁先谁后
顺序:先构造父类,再构造子类,析构的顺序与构造的顺序相反
继承中同名成员处理
问题:当子类和父类出现同名的成员,如何通过子类对象,访问到子类或者父类中同名的数据呢?
访问子类同名成员,直接访问即可
访问父类同名成员,需要加作用域
继承同名静态成员处理
问题:继承中同名的静态成员在子类对象上如何进行访问?
静态成员和非静态成员出现同名,处理方式一致(除了非静态没有两种访问方式)
访问子类同名成员 直接访问即可
访问父类同名成员 需要加作用域
有两个访问方式:1.通过对象方式访问
2.通过类名方式访问
多继承语法
多继承语法:
C++允许一个类继承多个类
语法:class 子类:继承方式 父类,继承方式 父类2...
多继承肯会引发父类有同名成员出现,需要加作用域区分。
c++实际开发中不建议用多继承.
子类中的内存字节:16个
菱形继承
菱形继承概念:
两个派生类继承一个基类
又有某个类同时继承着两个派生类
这种继承被称为菱形继承,或者砖石继承。
菱形继承问题:
1.养继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。
2.草泥马继承自动物的数据继承了两份,其实我们应该清除,这份数据我们只需要一份就可以。
案例:
关键字:virtual
总结:菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
利用虚继承可以解决菱形继承问题
3.多态(面向对象三大特性之一)
多态的基本语法:
多态分为两类:
静态多态:函数重载和运算符重载属于静态多态,复用函数名
动态多态:派生类和虚函数实现运行时多态
静态多态和动态多态的区别:
静态多态的函数地址早绑定 编译阶段确定函数地址
动态多态的函数地址晚绑定 运行阶段确定函数地址
重写概念:函数返回值类型 函数名 参数列表 完全相同
动态多态满足条件
1.有继承关系 2.子类重写父类的虚函数
动态多态使用条件:父类的指针或者引用 指向子类对象
多态的原理分析
多态案例1-计算器类
多态案例—计算器类
案例描述:分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类
多态的优点:
代码组织结构清晰
可读性强
利于前期和后期的扩展以及维护
总结:C++开发提倡利用多态程序设计架构,因为多态优点多。
纯虚函数和抽象类
纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容。因此可以将虚函数改为纯虚函数
纯虚函数语法:virtual 返回值类型 函数名 (参数列表)=0;
当类中有了纯虚函数,这个类也称抽象类。
抽象类特点:无法实例化对象 子类必须重写抽象类中的纯虚函数,否则也属于抽象类。
多态 案例2—制作饮品
案例描述:制作饮品的大概流程为:煮水 冲泡 倒入杯中 加入佐料。
利用多态技术实现本案例 :提供抽象制作饮品基类,提供子类制作咖啡和茶叶
虚析构和纯虚析构
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类的析构函数改为虚析构或者纯虚析构
虚析构和纯析构区别:如果纯虚析构,该类属于抽象类,无法实例对象
虚析构语法:virtual~类名(){}
纯虚构造语法:virtual ~ 类名()=0; 类名::~类名();
纯虚析构 需要声明也需要实现 有了纯虚析构之后 这个类也属于抽象类 无法实例化对象
总结:
1.虚析构或者纯虚析构就是用来解决通过父类指针释放子类对象
2.如果子类中没有堆区数据,可以不写虚析构或纯虚析构
3.拥有纯虚析构函数的类也属于抽象类
多态案例三——电脑组装
案例描述:电脑主要组成部件为CPU(用于计算),显卡(用于显示),内存条(用于存储),将每个零件封装出抽象类,并且提供不同的厂商生产不同的零件,例如Intel厂和Lenovo厂商
创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口
测试组装三台不同的电脑进行工作
代码: