|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 代号3 于 2018-4-30 11:40 编辑
多态 模版
数组中保存不同类型的对象:在多个类之上增加一个父类 数组使用父类的类型
后遗症:
数据保存不完整 高精度赋值给低精度精度丢失
解决:不保存完整对象 保存对象的地址 指针数组
父类通过数组元素调用成员函数时不能调用子类成员函数
解决:创建虚函数 前边加virtual (类型前) 父类中函数声明为虚函数
多态
对相同的指令做出不同的应答
实现
静态联编 (早期联编) 默认方式
重载
重定义
都会在编译阶段确定具体使用怎样的应答(函数体)来回应指令(函数调用)
动态联编 多态基础(晚期联编) ?静态地位//有多即动 非多即静
特定场合调用虚函数
父类指针调用虚函数的时候能够动态识别出指针指向类型,自动指向该类型同名
成员函数
触发
必须被调用函数为虚函数 否则默认静态联编
使用父类指针指向子类对象
使用父类指针调用虚函数
eg:
class Animal{};
calss Dog:public Animal{};
int main
{
Animal aniObj;
Dog dogObj;
Animal *pAni=nullptr;
Dog*pDog=nullptr;
aniObj.sound();//不会触发 调用Animal类的函数
dofObj.sound();
pAni=&anObj;
pAni->sound();//不会触发 调用Animal类的函数
pDog=&dogObj;
pDog->sound();//不会触发 调用Dog类函数
pAni=&dogObj;
pAni->sound();//会触发 调用Dog类函数 此时调用函数为虚函数 父类指针指向子类对象
}
多态原理
动态联编之后 父类指针如何识别出指针指向哪个子类对象 ?重载// 满足重写才能实现重载
虚函数表
当一个类有一个及以上的虚函数时 这个类定义出的对象大小会增加4个字节
(在对象的首地址处 内容为地址(虚函数表))
地址(虚函数表)储存的是一个数组
数组内存档地址(内容为子类对象的函数地址)) 此时就可以调用子类对象中的函数
增加虚函数的时候 虚函数列表增加 ?指针移位实现//编译器自主决定
//虚函数表只有一个 内容可多个(重编译解决数组大小问题) 虚函数可以多个
子类重新实现一个虚函数 虚函数表保存的是子类的虚函数地址(子类作为父类时实现多态)
几个 重写?还是另写// 全部刷新 父类被覆盖 不能再被使用
子类没有重新实现虚函数 虚函数表保存的是父类的地址
虚函数
定义
virtual+基类中的成员函数 编译器会认为该成员函数可能在派生类中存在不同的实现版本
使用
基类中的函数说明为虚函数
定义基类的公有类派生 基类的公有派生类中重写虚函数(基虚子皆虚)
重写虚函数不是重载函数 要求全部相同
基类派生重写可以省略virtual
功能
允许函数调用与函数体的联系在运行时才动态给出
原理
指针保存不同对象
限制条件
类的成员函数才能说明为虚函数 虚函数仅适用与有继承关系的类对象
静态成员函数不能是虚函数 无法构成重写
正常一个子类被释放时会主动调用其父类的析构函数
使用父类指针指向子类对象 当释放该父类指针时 会调用父类的析构函数
此时子类中若有堆内存的申请 会造成内存泄露(delete基类指针只调用父类的析构函数
子类不被调用)
解决:
将析构函数定义为虚函数(构造函数不能是虚函数 析构可以) ?//非唯一 自动调用析构时使用
重载 重定义 重写异同
作用域 函数名 参数
重载 相同 相同 不同 overload
重定义 不同 相同 相同 /不同 override
重写 不同 相同 相同 overwrite
重写 ?实现原理 重定义?//虚函数列表实现 动态联编
子类虚函数覆盖基类虚函数
特征
不同范围(子类与基类)
函数名相同
参数相同
基类函数中必须有virtual关键字
纯虚函数
在基类中不对虚函数给出有意义的实现 仅作为统一的编程接口使用 实现留给该基类
的派生类去做
语法格式
class <类名>
{
virtual <函数类型 ><函数名>(<参数表>)=0;
}
抽象类
一个类中定义了纯虚函数(一个或以上) 这个类会变成抽象类
只能作为基类用
抽象类不能直接实例化创建(不能声明抽象类对象) 可以声明抽象类的指针和引用
可使用指向抽象类的指针支持运行时多态性
继承抽象类必须重写所有虚函数 否则此类仍然是抽象类
若是子类继承基类抽象类 给出虚函数
?//纯虚函数未实现 子类中重写父类虚函数 此时虚函数表为子类
子类型
特定类型s当且仅当至少提供了类型t的行为s 称 s类型是类型t的子类型
s可以有新的行为
子类型关系不可逆
模板
函数模板
类模板 加class
限制条件
成员函数在类外定义的时候必须要放在同一个头文件里。加类名
(不能在.cpp中 会报错且不好查找)
语法
template<参数化类型名表>
<返回类型><函数名>(<参数表>)
{
函数体
}
eg:
template<typename T_Type>
int fun(T_Type NumA,T_Type NumB,~~~~~~)
{
}
类类型需要加关键字class
template <class T_Type>
{}
函数模版是模板的定义 不是函数 定义中使用通用的类型参数
模板函数是用函数模板实例化的函数,是事实上的函数定义。
模板函数
函数名(实参数),当实参数与函数模板参数相匹配的时候,则产生一个重载函数。
重载函数与函数模板实现功能相同(函数体定义相同)则成该重载函数为模板函数。
模板特化(实例化)
偏特化
所有类型的某一种类型的某几项进行特别处理
普通特化
模板所有替换类型的某一类型进行特别处理
|
|