软件开发笔记
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一.多继承
1.1
一个类 可以多个父类 构建这个对象的顺序
和这个类 继承类的顺序相关。
如果继承的数据 不产生冲突 则可以直接调用,
如果产生冲突可以使用 父类名作用域区分,
使用名字隐藏机制 也可以解决。
1.2 多继承代码的优化
把父类中的 共同成员 抽取出来
double price;
double getPrice(){ }
放入一个更高层的类中
然后使用 虚继承 继承最高层的类
对直接子类而言 和 普通继承的区别 只是
多出了一个指针 维护虚继承关系。
对子类的子类而言 不在从父类中拷贝 最高层
类的数据,而是直接访问最高层的类 和 最高
层类的子类 没有什么区别。但要付出维护虚
继承的代价。
二.虚函数
虚函数 是在普通成员函数上 加了virtual 修饰。
一个类型 如果有序函数 则编译器提供一个指针
指向这个类型的虚函数表。虚函数表中的元素就
是每个虚函数的地址。
这个指针的值存入对象的前四个字节。
三.对虚函数的重写(over write)
函数重写: 是针对虚函数 重写要求函数名相同
参数列表相同 返回值相同。
名字隐藏: 在子类中 出现和父类同名的数据。
函数重载:(over load) 同一个作用域 函数名
相同 参数列表不同。
四.多态
4.1 概念
当父类对象的指针(或引用) 指向 子类对象时
调用父类中提供的虚函数 表现将会是子类中
函数覆盖的实现。
4.2 多态的基础 是继承
虚函数是多态的关键
函数覆盖是必备条件
4.3 写一个动物类 Animal 有一个虚函数 run
还有一个虚函数 fun
还有一个非虚函数 show
写一个子类 Cat 覆盖run 和 fun show
再写一个子类 Fish 覆盖run 和 fun show
然后使用 Animal 指针 分别指针 Cat 和
Fish类型的对象 调用 fun run show
观察表现。
4.4 多态的使用
作为函数的参数
可以做到类型的通用
可以在函数内部 根据实际对象类型做出
相应的动作(虚函数)
函数的返回值
4.5 多态的原理
虚函数表指针
虚函数表
每一个类型都有自己类型对应的虚函数表。
同类型的对象共享虚函数表。
子类和父类的虚函数地址不同。
Animal *pa
if(a==1){
pa=new Cat();
}else if(a==2){
pa=new Dog();
}
pa->run();
4.6 类型上通用,方便了编程。但同时损失了
对象的一些个性。但有时我们需要识别
出对象真正的类型 进而恢复对象的个性。
具有多态性的父子之间
dynamic_cast<类型>(对象)
必须具有 虚函数 转换成功 就返回一个
合法地址 转换失败 就返回NULL。
typeid 获取一个对象 或者类型的 类型信息
#include
type_info typeid(对象|类型)
name() 得到类型的名字
== 判断两个类型的type_info 是否
一致就是同一类型。
!= 判断两个类型的type_info 是否
不等。
如果一个父类对象的指针 指向子类对象时
一定要确保父类型中有虚函数,如果没有
虚函数 则会把指向的对象 识别成父类类对象。
五.虚析构函数
当父类对象指针 指向子类对象时 如果释放
对象空间,则会调用父类的析构函数不会调用
子类的析构函数。
当父类型中出现 虚函数时 则应该在父类的
析构函数前加virtual修饰。
六.抽象类
一个类中有 纯虚函数时 则这个类就是抽象类。
抽象类不能被实例化,初次之外和正常的类没有
任何区别。
class A{
public:
/* 这就是纯虚函数 */
virtual void show()=0;
};
如果子类没有实现 纯虚函数 则子类成为抽象类。
纯抽象类:除了构造和析构之外 其它所有的函数
都是纯虚函数。