多态
-
概念: 同样的消息被不同类型的对象接收后,导致了不同的行为。(不单单能继承前人写的代码,也能复用前人的代码)
-
根据实际的“对象类型”决定函数语句的具体目标
-
问题:
-
由于类型兼容性原则,参数是基类指针,无论接收到的实参是基类地址还是派生类地址,都会被转化成基类指针。但是我们不想这样
-
解决方案: 虚函数 (关键字virtual)
-
就变得智能了
-
语法规则:
-
virtual 函数返回值类型 函数名(参数列表)
-
注:虚函数只能出现在类成员的原型声明中,而不能出现在成员函数的类外实现中
-
-
-
-
-
-
多态的类型:
-
重载多态:函数的重载,运算符的重载,
-
强制多态:将整型和浮点相加,先类型强转再相加
-
参数多态:模板
-
包含多态:虚函数
-
-
实现的角度看多态:
-
静态绑定和动态绑定
-
静态绑定(编译时多态):在程序编译的过程中确定同名的操作的具体对象,根据提前写好的类型来使用
-
动态绑定(运行时多态):程序运行时才确定具体的操作对象。这一过程叫 迟绑定。(demo2.test1)
-
注:虚函数的使用只能在类的非静态成员中。
-
-
-
-
实现包含多态的条件
-
满足继承关系
-
声明的虚函数必须是 非静态成员函数
-
由函数来调用或者通过指针和引用来访问虚函数
-
-
Vptr 虚函数表指针 只有函数名 参数 返回值 都相同才能实现多态。
-
-
例子demo2/test4.cpp-动物
-
-
-
虚析构函数(test5.cpp)
-
不能声明虚构造,但是可以声明虚析构函数
-
虚析构 在使用基类指针的时候用适当的析构函数对不同的对象实现清理(引导delete去清理不同类型的对象)。
-
由于类型兼容性原则 delete会只释放基类的内存,无法释放子类的,所以需要在析构函数前加virtual 关键字 来引导delete释放子类的内存
-
-
-
重写 重载 重定义
-
函数重载
-
相同范围(同一个类)
-
函数名相同
-
参数不同
-
virtual可有可无
-
-
-
隐藏(派生类的函数屏蔽了与其同名的基类函数)
-
4.1 如果派生类的函数和基类的函数同名,但是参数不同,此时无论是否有virtual关键字,基类函数都将被隐藏
-
4.2 如果派生类的函数和基类的函数同名,且参数也相同,但是基类没有virtual关键字,基类的函数将被隐藏
-
-
重定义
-
不同的范围(分别位于派生类和基类)
-
函数名相同
-
参数也相同
-
基类没加virtual关键字
-
-
-
覆盖(派生类函数覆盖基类函数) 重写
-
2.1 不同的范围(分别位于派生类和基类)
-
2.2 函数名相同
-
2.3 参数也相同
-
2.4 基类必须加virtual关键字
-
-
-
-
虚继承 (解决亲缘继承的问题,而且是对他的子类做操作,只保留一份副本,解决二义性问题,不知道在哪条路继承)
-