C++ 与 C 强制类型转换的区别
- C 可以在任意类型之间转换,不安全;C++ 相对比较安全。
- C 难以查询定位。C++ 易于追踪,
grep -rn "cast-name"
语法形式:
cast-name <type> (expression)
1 、static_cast
基础类型间的转换
- 基本数据类型间的转换,不能用于无关类型的转换。
- void 指针转换成目标类型的指针,任何类型的表达式转换成 void 类型。
double d = static_cast<int>(i); // ok, 用于基本数据类型间的转换 int *pInt = static_cast<int*>(pVoid); // ok,void 指针转换成目标类型的指针 float *pFloat = static_cast<float *>(pInt); // error,不能用于无关类型转换,不同指针类型间转换
2、dyamic_cast
用于下行转换(基类 -> 派生类),运行时动态检查。
类继承中的类型转换
- 上行转换:派生类 -> 基类,派生类指针或引用转换成基类指针或引用,安全。
- 下行转换:基类 -> 派生类,基类指针或引用转换成派生类指针或引用,不安全,需要动态类型检查 dyamic_cast,这是因为基类指针和引用可能指向的并不是一个子类对象。
// 同时完成类型转换和条件检查两个任务 // 1、转换成功 if (Derived *dp = dynamic_cast<Derived*>(bp)) { // 使用 dp 指向派生类对象 } // 2、转换失败 else { // 使用 bp 指向的基类对象 }
3、const_cast
移除类型的 const 或 volatile 属性。将常量对象转换成非常量对象。
const int number = 100; int *pInt2 = const_cast<int *>(&number); // ok,但是通过 pInt2 写值是未定义的行为 *pInt2 = 200
上述例子中提到的未定义的行为,const_cast 不是为了改变常量的值而设计的。话句话说,要修改值,一开始就应该定义为变量,何必多此一举定义为常量。const_cast 用于有函数重载的上下文中,例如:
const string &shorterString(const string &s1, const string &s2) { return s1.size() <= s2.size() ? s1 : s2; }
若对两个非常量的 string 实参调用这个函数,但是返回结果仍然是 const string 的引用。因此我们需要重载该函数,当实参不是常量的时候,返回普通引用。
string &shorterString(string &s1, string &s2) { // 实参强制转换成对 const 的引用,调用 shorterString 函数的 const 版本 auto &r = shorterString(const_cast<const string&>(s1), const_cast<const string&>(s2)); // 将返回的 const string 引用转换为普通的 string & return const_cast<const string&>(r); }
const_cast 用于函数重载,其他情况下使用则说明程序存在着某种设计缺陷。
4、reinterpret_cast
为运算对象的位模式提供较低层次上的重新解释。该运算符可以用来处理无关类型之间的转换,例如任意指针(引用)类型之间的转换。效果等同于 C 语言风格的强制类型转换。这样可能会导致未定义的行为,例如数字类型转换为指针类型。不同于 static_cast,使用 reinterpret_cast 没有安全检查,这一点要尤其小心。