catalog
动态/静态类型
静态类型, 在 程序中声明时, 就已经确定了, 而且用于不会改变
动态类型, 他只针对指针, 可以变化 通过赋值来改变
(非指针)变量, 他只有 (静态类型) Foo f; 则f 的静态类型为Foo, 没有动态类型
(指针)变量, 他 既有(静态), 也有 (动态)类型
Fa * fa;
(此时, fa的静态类型为: Fa *
, 动态类型为 无 (或者说, 没有动态类型)
)
fa = new Son1;
(此时, fa 的动态类型为 Son1 *
)
fa = new Son2;
(此时, fa 的动态类型为 Son2 *
)
fa = nullptr;
(此时, fa 又没有动态类型了)
virtual函数分类
一般, virtual函数分为: (pure virtual
纯虚函数, 即子类必须实现)
(impure virtual
非纯虚函数, 若子类实现 而覆盖, 否则使用 父类实现的版本)
多态的2种使用
- 指针
Son s; Fa * fa = &s; fa->func(); ' 会调用到: s.func() '
- 引用
Son s; Fa & fa = s; ' 或: const Fa & fa = Son(); <只有const引用, 可以绑定 临时对象> ' fa.func(); ' 会调用到: s.func() '
对于, dynamic_cast (即获取他的子类对象), 也有2个方式:
- 指针
Fa * fa = new XX; Son * son = dynamic_cast<Son *>( fa); if( son != nullptr){ cout << "success cast"; }
- 引用
与指针方式不同, (指针可以通过返回值是否是nullptr来判断, 因为如果转换失败则返回nullptr)try{ Fa * fa = new XX; Son & son = dynamic_cast< Son &>( *fa); } catch( const std::bad_cast &){ cout << "failed cast"; }
但引用方式, 转换失败, 会throw异常
dynamic_cast
效率
dynamic_cast
的效率很慢!!!
dynamic_cast
的原理是: 基于class名称
的 字符串比较
即, 他会将内存对象
和 继承体系里的每个子类
, 进行strcmp
匹配
多态数据获取
Fa * fa = new Son
我们令, 这个new Son
对象 为 son
这个fa
- fa->data, 一定对应为:
son->Fa::data
, 而不是son->data
!!! - fa->func, (如果func为虚函数, 且Son也有自己的实现: 则
fa->func
会调用son->func()
) (否则:fa->func()
会调用son->Fa::func()
)
即, 我们可能会误以为: 多态, 只是针对func
的多态; 对于数据data, 并无法使用多态
简单来说, 这种说法是正确的;
但是, 借助dynamic_cast
, 可以实现 对data
的多态!!!
Fa * fa = new Son
; 我们令, 这个new Son
对象 为 son
, 且: son->data = 1, son->Fa::data = 0
fa->data
可以来获取:son->Fa::data
- 那么:
son->data
如何通过fa
来获取呢??
Son * s = dynamic_cast< Son *>( fa);
, 此时, 这个s
对象, 和上面的son
对象, 是完全相同的!!
自然,s->data
就是son->data
虚函数/ 多态类
如何判断, 一个类是否是(多态类)呢
- 方法1:
- 当该类不是子类: 如果, 该类中 有
>=1
个 虚函数,虚函数: 虚成员函数 或 虚析构函数
, 则该类是多态类 - 当该类是子类: 如果, 其父类是多态类, 则该类是多态类
- 当该类不是子类: 如果, 该类中 有
- 方法2: 通过dynamic_cast, 下面会谈到
如果一个类有虚成员函数, 则你必须显式的 将他的 析构函数, 也写成 虚函数!!! 下面会解释为什么
即, 只要是多态类,则你必须显式的 将他的 析构函数 写成 虚函数
虚函数, 在类内 最好是声明
, 不要在类中实现出来!!!
dynamic_cast 与 多态类
dynamic_cast< A *>( B *)
要求:
B
类, 必须是 多态类, 否则报错!!!
dynamic_cast
对A
类, 没有任何限制!!! A 和 B
, 可以是完全毫无任何关系!!! 至少编译通过; 只是会强转失败而已
' 继承关系: SSON -> SON -> FA '
FA * ptr = new SSON;
using T = FA / SON / SONN;
T