虚函数dynamic_cast
引用
dynamic_cast<type>()
动态转换只支持方法多态类型的指针,如果转换成功返回指针,失败则返回nullptr
同样分为两种情况:
- 向下转换 downcast
- 跨类转换 crosscast
注:不要随便转换this指针
还有一点,当dynamic_cast用于转换引用时,转换失败会抛出异常,所以一般不推荐转换引用
正文
1 | class father{ |
还是之前的例子
1 | son s1; |
正常情况下我们知道静态转换可以这么操作。
1 | son s1; |
虽然强转,但是毕竟父类和子类结构不一样,指针的时候不是很理想。
1 | son *s2 = dynamic_cast<son *>(fh); |
用动态转换的时候他要求类是一个多态类,那么在基类中加一个虚函数
1 | class father{ |
然后编译就能通过了,对此是否完成转换,前面提到过转换成功返回指针,没成功返回nullptr。
显然是失败了,因为fh指针我们重新new了一个father类型。导致和son不同。
1 | son s1; |
当我们注释掉重新new的那句,fh仍然指向一个son类型的,那么它的指针信息就会和son有关。
不要过度依赖
1 | class father{ |
然后无脑为了转换基类指针,然后调用各自的move
1 | auto sp = dynamic_cast<son *>(fh); |
这些全是下饭操作,这其实没有必要去做什么动态转换,直接在基类里面加一个虚函数,子类重写一下直接调用是最快的。
不可取
不要乱玩this指针
1 | class father{ |
假设基类中有虚函数,它对this指针进行了一些操作,那么当派生类继承下来的时候,就全是在派生类上动手脚了,虽然语法规定没有限制不能转换this指针,但是不推荐这么操作,大多情况下人都把握不住。
强转指针和引用
之前说为了保证数据的完整,建议都是通过指针或者引用转换。
1 | son s1; |
这两种强转都是没有什么问题的,引用本身就是弱化的指针。
而当使用dynamic_cast
的时候,也是前面提到过的问题。
1 | son *s2 = dynamic_cast<son *>(fh); |
当dynamic_cast
去做引用的转换时,他如果出错了不是返回nullptr而是抛出异常。
在底层上,指针存在空指针,而引用没有空引用的说法。
跨类转换
1 | class father{ |
构建一个新类box,他跟father之类的毫无关系,但是他被werewolf继承。
那么这个类还适合转换吗?
1 | werewolf wf; |
因为存在多重继承,向下继承的适合自己推敲有点麻烦,就看看动态能不能直接完成。
1 | auto p = dynamic_cast<Box *>(fa); |
显然是可以的。
他是成功返回了一个指针,而不是nullptr。
那么在关联上
father和box是没有直接关系的,但是werewolf继承了这两个,因此包含了他俩的属性,所以werewolf可以主动转换成father和box类型。
结语
迷迷糊糊。