1 dynamic_cast :
dynamic_cast的语法:
dynamic_cast <type_name> (expression)
书上有两个地方说了dynamic_cast的用途:
dynamic_cast运算符的用途是,使得能够在类层次中进行向上转换
仅当Low是High的可访问基类时,下面的语句才会将一个Low*指针赋给pl:
pl = dynamic_cast<Low*>ph ; //说明下其中ph是派生类指针,pl是基类指针
否则,该语句将空指针赋值给pl
由此可见:使用dynamic_cast的用途是:实现安全的向上转换,如果转换不成功,那么就会把被赋值的指针赋值为nullptr .
2 static_cast :
static_cast的语法:
static_cast <type_name> (expression)
主要用于将expression类型强制转换为type_name诶型. 那么我们需要知道如何判定转换是否合法?
书上的转换是否合法是这么判定的,姑且称为转换合法原则:
当type_name可被隐式转换为expression所属的类型或者expression可被隐式转换为type_name所属的类型时,转换是合法的,否则将出错
摘录出来就是:
以下条件只要满足任一条,则转换合法:
1 ) type_name可被隐式转换为expression所属的类型 ;
2) expression可被隐式转换为type_name所属的类型.
我们结合书上给出的例子来看一下:
High 是一个基类 ,Low是 High类的一个派生类,有如下代码:
High bar; //基类
Low blow; //派生类
...
High *pb = static_cast<High *>(&blow); //blow是派生类,pb是基类的指针,因此这里是向上转换,合法
Low *pl = static_cast<Low *>(&bar); //bar是基类,pl是派生类指针,因此是向下转换,合法
为什么上述两个转换都是合法的呢?
其实原因就一条,我们都知道,在派生关系中, 基类的指针可以直接指向一个派生类的对象,这个过程不需要显式转换 ,因此结合上述的转换合法原则,我们来分析一下上述两句转换的合法性:
1) High *pb = static_cast<High *>(&blow); // High *是 type_name ,&blow所属的类型是Low * , 因为 High* 可以被隐式的转换为Low* ,这符合转换合法原则的前种情况 “ type_name可被隐式转换为expression所属的类型” ,因此转换合法;
2) Low *pl = static_cast<Low *>(&bar); // Low *是 type_name ,&bar所属的类型是High * ,还是因为 High* 可以被隐式的转换为Low* ,这符合转换合法原则的后种情况 “expression可被隐式转换为type_name所属的类型”,因此转换合法.
因此,我们可以看到static_cast可以把原来只允许单向转换的场景变成允许双向转换,类似的情况有:
1 一般来说,可以把任意的数据类型指针赋值给void *指针 ,但是不能把 void *指针赋值给任意数据类型的指针, 如果使用了static_cast ,那么就可以实现把void * 赋值给 任意数据类型;
2 一般来说, 我们可以把int类型赋值给double类型,但是不能把 double类型的赋值给int类型 ,但如果使用了static_cast ,那么就可以把double类型赋值给int类型
3 一般来说,我们可以把一个枚举类型enum直接赋值给int ,但是不能把int直接转换为enum,但如果使用了static_cast ,那么就可以实现这种转换
….
类似的情况,大家可以继续发散..总之 ,原则就一条 : 能不能合法转换,主要取决于type_name和expression之间要存在任一方向的隐式转换关系.
但是至于转换后的内容是否安全,这是开发需要自行保证的,编译器无法保证.