10. 强制类型转换

10.1. static_cast<type> (expr)

1. static_cast 作用和 C 语言风格强制转换的效果基本一样,由于没有运行时类型检查来保证转换的安全性,所以这类型的强制转换和 C 语言风格的强制转换都有安全隐患。

2. 用于基本数据类型之间的转换,如把 int 转换成 char ,把 int 转换成 enum 。这种转换的安全性需要开发者来维护。

3. C++ 的任何的隐式转换都是使用 static_cast 来实现。

4. 基类和子类之间转换:其中子类指针转换成父类指针是安全的;但父类指针转换成子类指针是不安全的。(基类和子类之间的动态类型转换建议用 dynamic_cast

5. 把空指针转换成目标类型的空指针。

6. 把任何类型的表达式转换成 void 类型。

10.2. dynamic_cast<type> (expr)

type 可以是指针、引用、右值引用。

有条件转换,动态类型转换,运行时类型安全检查(对于指针,转换失败返回 NULL ;对于引用,抛出 std:bad_cast 异常)。

1. 安全的基类和子类之间转换。

2. 必须要有虚函数;必须是公有继承(public)。

3. 相同基类不同子类之间的交叉转换,结果是 NULL 或抛出 std:bad_cast 异常。

 1// dynamic_cast
 2#include <iostream>
 3#include <exception>
 4using namespace std;
 5
 6class Base { virtual void dummy() {} };
 7class Derived: public Base { int a; };
 8
 9int main ()
10{
11  try
12  {
13    Base* pba = new Derived;
14    Base* pbb = new Base;
15    Derived* pd;
16
17    pd = dynamic_cast<Derived*>(pba);
18    if (pd == 0) cout << "Null pointer on first type-cast.\n";
19
20    pd = dynamic_cast<Derived*>(pbb);
21    if (pd == 0) cout << "Null pointer on second type-cast.\n";
22
23  } catch (exception& e) {cout << "Exception: " << e.what();}
24  return 0;
25}
26
27// 输出结果:Null pointer on second type-cast.

10.3. const_cast<type> (expr)

1. 去掉类型的 constvolitale 属性(对象本身的属性没有改变);

2. 常量指针被转化成非常量的指针,并且仍然指向原来的对象;

3. 常量引用被转换成非常量的引用,并且仍然指向原来的对象;

4. const_cast 一般用于修改指针。如 const char* p 形式。 如果有一个函数,它的形参是 non-const 类型变量,而且函数不会对实参的值进行改动,这时我们可以使用类型为 const 的变量来调用函数,此时 const_cast 就派上用场了。

 1// const_cast
 2#include <iostream>
 3using namespace std;
 4
 5void print (char* str)
 6{
 7  cout << str << '\n';
 8}
 9
10int main ()
11{
12  const char* c = "sample text";
13  print ( const_cast<char *> (c) );
14  return 0;
15}
16
17// 输出结果:sample text

10.4. reinterpret_cast<type> (expr)

1. reinterpret_cast 是从底层对数据进行重新解释,依赖具体的平台,可移植性差。

2. reinterpret_cast 可以将整型转换为指针,也可以把指针转换为数组。

3. reinterpret_cast 可以在指针和引用里进行肆无忌惮的转换。

10.5. 使用stringstream转换类型

#include <sstream>

sstream 头文件定义了三个类型来支持内存IO:istringstream,ostringstream,stringstream。这些类型可以向 string 写入数据,或从 string 读取数据。

stringstream 的一些操作:

  • stringstream strm :strm 是一个未绑定的 stringstream 对象

  • stringstream strm(s) :strm 是一个 stringstream 对象,保存字符串 s 的一个拷贝

  • s = strm.str() :返回 strm 保存的内容的拷贝

  • strm.str(s) :把 strm 保存的内容修改为 s,丢弃之前的内容。

强制类型转换

 1#include <iostream>
 2#include <sstream>
 3using namespace std;
 4
 5template <class output_type, class input_type>
 6output_type Convert(const input_type &input)
 7{
 8  stringstream strm;
 9  strm << input;
10  output_type result;
11  strm >> result;
12  strm.clear();
13  return result;
14}
15
16
17int main(int argc, char ** argv)
18{
19  string strNum = "-22.22";
20  float f = Convert<float>(strNum);
21  cout << f << endl; // -22.22
22
23  float n = 22.22;
24  string str = Convert<string>(n);
25  cout << str << endl; // 22.22
26
27  return 0;
28}

Note

strm调用 成对的 <<>> 之后,状态为 end-of-file ,必须进行 clear 才能进行下一次 << 操作。

strm.clear() 重置了strm的状态标识,并没有清空数据。如果没有调用 << 之后没有使用 >> ,可以使用 strm.str("") 清空数据。

10.6. 参考资料

  1. C++中四种强制类型转换区别详解

  1. c++ 四种强制类型转换介绍

  1. C++中使用stringstream简化类型转换

  1. c++ reference

  1. C++强制类型转换操作符 const_cast