多态
一.概念:相同对象收到不同消息,或者,不同对象收到相同消息
二.静态多态(早绑定):在编译时,已确定使用哪个函数(eg:函数同名异参—函数重载)
三.动态多态(晚绑定):在运行时,才确定使用哪个函数
virtual关键字:
一.不能使用virtual的函数
(1)全局函数:即普通函数,否则编译报错
(2)静态成员函数:与类共生存,而非对象,否则编译报错
(3)内联函数函数:inline失效
(4)构造函数:编译报错
二.virtual写法建议:
(1)统一写在前面:
virtual public Person; //虚继承
//在类的头文件中声明并定义
virtual inline void test(){ } //不用分号
(2)即便默认有virtual,也要加上virtual(eg:待实现/已实现的纯虚函数)
(3)基类的析构函数均加上virtual,防止因构造函数中申请堆内存,而未在析构函数中释放,导致内存泄漏
虚函数表
一.指针例举分类:
(1)指向对象入口地址:对象指针
(2)指向函数入口地址:函数指针
(3)指向虚函数表入口地址:虚函数表指针
二.虚函数表
(1)概念:每个类(除了空类,就是没有方法也没有属性的类)在创建的时候,就会生成一个虚函数表指针vftable_ptr,虚函数表中存着对象的虚函数指针
(2)说明:(该内存示意图片来自imooc)
Circle对象通过vftable_ptr找到虚函数表,经过偏移找到某个虚函数的指针
A.对象的大小:数据成员的大小+虚函数指针(32位4字节,64位8字节)
(若两者均不存在,则以1个字节标记对象的存在)
B.虚函数指针在对象内存中占第一个
Ps:指针++,每次走4个字节
(3)弊端:维持表,需要加大系统开销
(4)情况:
(若子类重写父类的方法,则关于该方法在各自虚函数中入口地址不一样,否则一样)
A.父类实现了非virtual修饰的方法一,子类继承父类,子类没有再实现方法一
B.父类实现了非virtual修饰的方法一,子类继承父类,子类重写了方法一:(即隐藏)
父类指针指向子类对象的时候,调用方法一时会用父类虚函数表中方法一的入口
子类调用方法一时,使用的是子类虚函数表中的方法一的入口
C.父类实现了virtual修饰的方法一,子类继承父类,子类没有再实现方法一:同A
D.父类实现了virtual修饰的方法一,子类继承父类,子类重写了方法一:(即覆盖)
在父类指针指向子类对象时,父类的虚函数表方法一的入口地址会被子类的覆盖,从而多态
纯虚函数
一.定义:没有方法体,且等于0的虚函数(在虚函数表中的指针值为0)
二.举例:
virtual double test()=0;
三.抽象类:
(1)定义:含有纯虚函数的类
(2)特点:不能直接实例化,否则编译报错;
但子类实例化时,抽象类会被间接实例化
(3)子类:抽象类的子类实现所有的纯虚函数才不是抽象类
四.接口类:
(1)概念:仅含有纯虚函数
(2)使用:
A.接口类只需.h文件
B.实现接口类的子类必须声明将所有的纯虚函数声明为虚函数
RTTI(运行时类型识别 Run-Time Type Idetification)
一.typeid:
(1)头文件:需添加#include,不然typeid无法使用,程序无法编译的
(2)适用:任何数据类型,包括对象,类(但只能获取对象的实际类型)
(3)示例:
typeid(int);
typeid(*obj).name(); //obj为指针
typeid(Bird); //Brid为类
(4)返回:type_info对象的引用
(5)注意:要返回实际类型,则基类必须有虚函数,否则为定义时类型
二.dynamic_cast:
1.适用:
(1)某个类型指针和引用的转换,即不能是某个类型本身
(2)源转换类型必须包含虚函数,否则转换失败
(3)转换成功,返回子类对象的地址,否则NULL
2.示例:
dynamic_cast<Brid *>(obj);//obj 是指向基类的指针,不能直接操作子类的方法。
异常处理
一.引入:避免异常抛至操作系统,操作系统直接关闭程序,对用户不友好
二.过程:
三.基本思想:主逻辑和异常处理分开
四.用法:
fun(){
throw string(“exception”);
}
fun1(){
throw SizeErr();
}
(1)catch(类型):
Int main(){
try {
fun();
}
catch(string){
...
}
catch(...){ //捕获任何类型
...
}
return 0;
}
(2)catch(值):
int main(){
try {
fun();
}
catch(string &aval){
cout<<aval<<endl;
}
return 0;
}
五.常用异常:下标,除数为0,内存不足(死循环,或者内存泄漏)
六.多态:(Exception接口类) 下图来自imooc网
int main(){
try {
fun()1;
}
catch(Exception &e){
...
}
return 0;
}