C语言类型转换
c语言类型转换有如下两种(旧式转型)
1 | (T)expression //将 expression 转型为T |
C++新式类型转换
C++类型转换有如下四种
1 | const_cast<T>(expression) |
const_cast
一般用于移除对象的const与volatile。如下图所示,b可以修改a的值。但是注意,编译器会进行优化,将数字常量1替代a常量。所以cout << a << endl;输出为1。
1 |
|
dynamic_cast
dynamic_cast 主要作用是将指向派生类对象的基类指针或引用,安全的转换为指向派生类对象的派生类指针或引用,并使用转换后的指针调用派生类独有的函数(非虚函数)。如果转换指针转换失败,则将返回空指针;如果转换引用失败,则将会抛出一个名为std::bad_cast的异常。
在如下3种情况中转换可以成功
- expression的类型与待转换类型相同。则转换必定成功。
- expression的类型为待转换类型的公有派生类。(指针向上转换)
- expression的类型为待转换类型的公有基类时,必须满足以下两个要求,才会转换成功,否则转换失败。(指针向下转换)
- 当expression为指向派生类的指针或引用派生类对象的基类引用。
- 基类中必须包含虚函数,也就是必须具备多态性。
假设有如下两个类
1 |
|
example:
1 | int main(int argc, char *argv[]) |
reinterpret_cast
reinterpret_cast 主要的作用为允许任意长度相同的对象之间进行转换,而转换的安全性,则全部由程序员所保证,它只关注对象之间长度是否相同,长度不相同则无法通过编译。注意,reinterpret_cast无法去掉源对象的const、volatile属性。
1 | int main(int argc, char *argv[]) |
需注意在32位机器上,指针为4字节,而在64位机器上,指针为8字节。
static_cast
static_cast 类似C语言强制类型转换,它可以完成如下一些转换
- 编译器隐式执行的类型转换,如int与float、double与char、enum与int之间的转换等。(精度大->精度小使用位截断处理)
- 将任意类型表达式转换为void类型,或从void*指针中找回其中的值。
- 基类与派生类指针或引用类型之间的转换,注意,由派生类转换至基类时(向上转换)是安全的,由基类至派生类转换时(向下转换)是非安全的。
example(使用上述代码定义的类):一下内容取自effective C++1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20int main(int argc, char *argv[])
{
char a = 'a';
//将 char -> int
int i = static_cast<int>(a);
Base* b = new Base("123");
//将 Base 转换为 void*
void* v = static_cast<void*>(b);
//将 *void 转换为 Base
b = static_cast<Base*>(v);
Derived* d = new Derived("123", 123);
//向上转换 将Derived* 转换为 Base*
Base* bb = static_cast<Base*>(d);
//向下转换 将Base* 转换为 Derived*
Derived* dd = static_cast<Derived*>(b);
//未定义的行为!非常危险!父类对象并不包含该函数,编译不会报错!
dd->PrintIval();
}如果可以,尽量避免转型,特别是在注重效率的代码中避免 dynamic_cast。如果有个设计需要转型的动作,试着发展无需转型的替代设计。
如果转型是必要的,试着将它隐藏至某个函数背后,客户随后可以调用该函数,而不需将转型放进他们的代码内。
宁可使用C++-style(新式转型),不要使用旧式转型。前者很容易辨识出来,而且有其不同的职责。

