C++ 将类型名作为强制类型转换运算符。

C++ 引入了四种功能不同的强制类型转换运算符以进行强制类型转换:static_cast、reinterpret_cast、const_cast 和 dynamic_cast。

强制类型转换是有一定风险的,有的转换并不一定安全,如把整型数值转换成指针,把基类指针转换成派生类指针,把一种函数指针转换成另一种函数指针,把常量指针转换成非常量指针等。C++ 引入新的强制类型转换机制,主要是为了克服C语言强制类型转换的以下三个缺点。

1 没有从形式上体现转换功能和风险的不同。

例如,将 int 强制转换成 double 是没有风险的,而将常量指针转换成非常量指针,将基类指针转换成派生类指针都是高风险的,而且后两者带来的风险不同(即可能引发不同种类的错误),C语言的强制类型转换形式对这些不同并不加以区分。

2 将多态基类指针转换成派生类指针时不检查安全性,即无法判断转换后的指针是否确实指向一个派生类对象。

3 难以在程序中寻找到底什么地方进行了强制类型转换。

强制类型转换是引发程序运行时错误的一个原因,因此在程序出错时,可能就会想到是不是有哪些强制类型转换出了问题。

使用 C++ 的方式,只需要查找_cast字符串就可以了。甚至可以根据错误的类型,有针对性地专门查找某一种强制类型转换。例如,怀疑一个错误可能是由于使用了 reinterpret_cast 导致的,就可以只查找reinterpret_cast字符串。

C++ 强制类型转换运算符的用法如下:

强制类型转换运算符 <要转换到的类型> (待转换的表达式)

例如:

double d = static_cast <double> (3*5);  //将 3*5 的值转换成实数

下面分别介绍四种强制类型转换运算符。

static_cast

static_cast 用于进行比较“自然”和低风险的转换,如整型和浮点型、字符型之间的互相转换。另外,如果对象所属的类重载了强制类型转换运算符 T(如 T 是 int、int* 或其他类型名),则 static_cast 也能用来进行对象到 T 类型的转换。

static_cast 不能用于在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,当然也不能用于不同类型的引用之间的转换。因为这些属于风险比较高的转换。

static_cast 用法示例如下:

#include <iostream>
using namespace std;
class A
{public:operator int() { return 1; }operator char*() { return NULL; }
};
int main()
{A a;int n;char* p = "New Dragon Inn";n = static_cast <int> (3.14);  // n 的值变为 3n = static_cast <int> (a);  //调用 a.operator int,n 的值变为 1p = static_cast <char*> (a);  //调用 a.operator char*,p 的值变为 NULLn = static_cast <int> (p);  //编译错误,static_cast不能将指针转换成整型p = static_cast <char*> (n);  //编译错误,static_cast 不能将整型转换成指针return 0;
}

reinterpret_cast

reinterpret_cast 用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。转换时,执行的是逐个比特复制的操作。

这种转换提供了很强的灵活性,但转换的安全性只能由程序员的细心来保证了。例如,程序员执意要把一个 int* 指针、函数指针或其他类型的指针转换成 string* 类型的指针也是可以的,至于以后用转换后的指针调用 string 类的成员函数引发错误,程序员也只能自行承担查找错误的烦琐工作:(C++ 标准不允许将函数指针转换成对象指针,但有些编译器,如 Visual Studio 2010,则支持这种转换)。

reinterpret_cast 用法示例如下:

#include <iostream>
using namespace std;
class A
{public:int i;int j;A(int n):i(n),j(n) { }
};
int main()
{A a(100);int &r = reinterpret_cast<int&>(a); //强行让 r 引用 ar = 200;  //把 a.i 变成了 200cout << a.i << "," << a.j << endl;  // 输出 200,100int n = 300;A *pa = reinterpret_cast<A*> ( & n); //强行让 pa 指向 npa->i = 400;  // n 变成 400pa->j = 500;  //此条语句不安全,很可能导致程序崩溃cout << n << endl;  // 输出 400long long la = 0x12345678abcdLL;pa = reinterpret_cast<A*>(la); //la太长,只取低32位0x5678abcd拷贝给paunsigned int u = reinterpret_cast<unsigned int>(pa);//pa逐个比特拷贝到ucout << hex << u << endl;  //输出 5678abcdtypedef void (* PF1) (int);typedef int (* PF2) (int,char *);PF1 pf1;  PF2 pf2;pf2 = reinterpret_cast<PF2>(pf1); //两个不同类型的函数指针之间可以互相转换
}

程序的输出结果是:

200, 100
400
5678abed

上面程序中的各种转换都没有实际意义,只是为了演示 reinteipret_cast 的用法而已。在编写黑客程序、病毒或反病毒程序时,也许会用到这样怪异的转换。

reinterpret_cast体现了 C++ 语言的设计思想:用户可以做任何操作,但要为自己的行为负责。

const_cast

const_cast 运算符仅用于进行去除 const 属性的转换,它也是四个强制类型转换运算符中唯一能够去除 const 属性的运算符

将 const 引用转换为同类型的非 const 引用,将 const 指针转换为同类型的非 const 指针时可以使用 const_cast 运算符。例如:

const string s = "Inception";
string& p = const_cast <string&> (s);
string* ps = const_cast <string*> (&s);  // &s 的类型是 const string*

dynamic_cast

用 reinterpret_cast 可以将多态基类(包含虚函数的基类)的指针强制转换为派生类的指针,但是这种转换不检查安全性,即不检查转换后的指针是否确实指向一个派生类对象。dynamic_cast专门用于将多态基类的指针或引用强制转换为派生类的指针或引用,而且能够检查转换的安全性。对于不安全的指针转换,转换结果返回 NULL 指针。

dynamic_cast 是通过“运行时类型检查”来保证安全性的。dynamic_cast 不能用于将非多态基类的指针或引用强制转换为派生类的指针或引用——这种转换没法保证安全性,只好用 reinterpret_cast 来完成。

dynamic_cast 示例程序如下:

#include <iostream>
#include <string>
using namespace std;
class Base
{  //有虚函数,因此是多态基类
public:virtual ~Base() {}
};
class Derived : public Base { };
int main()
{Base b;Derived d;Derived* pd;pd = reinterpret_cast <Derived*> (&b);if (pd == NULL)//此处pd不会为 NULL。reinterpret_cast不检查安全性,总是进行转换cout << "unsafe reinterpret_cast" << endl; //不会执行pd = dynamic_cast <Derived*> (&b);if (pd == NULL)  //结果会是NULL,因为 &b 不指向派生类对象,此转换不安全cout << "unsafe dynamic_cast1" << endl;  //会执行pd = dynamic_cast <Derived*> (&d);  //安全的转换if (pd == NULL)  //此处 pd 不会为 NULLcout << "unsafe dynamic_cast2" << endl;  //不会执行return 0;
}

程序的输出结果是:

unsafe dynamic_cast1

如果上面的程序中出现了下面的语句:

Derived & r = dynamic_cast <Derived &> (b);

那该如何判断该转换是否安全呢?不存在空引用,因此不能通过返回值来判断转换是否安全。C++ 的解决办法是:dynamic_cast 在进行引用的强制转换时,如果发现转换不安全,就会拋出一个异常,通过处理异常,就能发现不安全的转换。

C++ 强制类型转换运算符相关推荐

  1. 重载new、delete和强制类型转换运算符()

    1.重载new和delete运算符 内存管理运算符new.new[].delete和delete[]也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就 ...

  2. C++编程进阶4(C++中的强制类型转换运算符、不要返回自定义类内部成员的指针,引用和迭代器)

    十五.C++中的强制类型转换 C语言中的强制类型转换方式有两种 T i = (T)exp; T i = T(exp); 这两种方式没有差别,C++中也支持这两种方式,但是和C++中的强制类型转换运算符 ...

  3. 区分一下强制类型转换运算符重载/赋值运算符重载/对象定义的赋值

    这三个名字可能很绕,看着也很不一样,但其实是三个很容易混淆的概念,并且经常在实际编程中遇到.这里拿出来比较一下. 首先是强制类型转换运算符的重载,作用是当前对象向其他类型的转换,常见的形式是 oper ...

  4. c语言运算符类型转换,C语言中强制类型转换运算符的独特作用

    C语言中强制类型转换运算符的独特作用 在C语言中有一个强制类型转换运算符,它为C语言中的数据类型转换带来 (本文共2页) 阅读全文>> 在进行C++类的设计时,我们常常需要为类对象设计运算 ...

  5. C++ 重载强制类型转换运算符

    C++ 中,类型的名字(包括类的名字)本身也是一种运算符,即类型强制转换运算符. 类型强制转换运算符是单目运算符,也可以被重载,但只能重载为成员函数,不能重载为全局函数.经过适当重载后,(类型名)对象 ...

  6. 强制类型转换运算符的优先级

    强制类型转换 int i=10; char b=20; 如:i=b;//这样赋值没有问题,因为低字节类型转换成高字节类型. 如果是b=i;//这样会有问题,b=(char)i;//因为高字体转换为低字 ...

  7. c++强制类型转换运算符

    static_cast •用于非多态类型的转换 •不执行运行时类型检查(转换安全性不如 dynamic_cast) •通常用于转换数值数据类型(如 float -> int) •可以在整个类层次 ...

  8. c语言--强制类型转换运算符

    当我们想改变一个表达式的类型时,"强制类型转换符",get it! 1.一般形式: (类型名)(表达式) 2.一般应用: (float) x                     ...

  9. 强制类型转换运算符—C++基础篇

    VC++中的四种强制转换类型运算符,const_cast,reinterpret_cast,static_cast,dynamic_cast 1, static_cast<T*>(a)  ...

最新文章

  1. c语言stm8变量存储类型,STM32存储资源分配解析
  2. android 学习记录-----------android 活动 意图 碎片
  3. LeetCode 2013. 检测正方形(字典)
  4. ubuntu软件中心打不开Python error
  5. 序列化(写对象)与反序列化(读对象)
  6. android自定义控件.pdf,android自定义控件实例(linearlayout组合textview和imageview).pdf
  7. 2003系统虚拟dns服务器向导,安装和管理dns服务器.doc
  8. 计算机设备问题代码43,双击unknown device由于该设备有问题Windows已将其停止(代码 43)怎么办解决教程...
  9. 雄迈XM530AI / 550AI模组相关参数介绍
  10. matlab根据数据进行降频,Ubuntu 下对CPU进行降频
  11. Python学习日记-day1基础篇 字符 输出 注释
  12. 什么叫逐行扫描和隔行扫描
  13. 申请支付宝授权,提现测试环境步骤
  14. 低成本精准营销助推中小企业度过经济寒冬
  15. 【免费开放源码】审批类小程序项目实战(活动历史页面)
  16. 批量作业调度工具 Taskctl 定时器及模块之间的区别
  17. 《浪潮之巅》阅读笔记之一
  18. Rhapsody 及 Doors安装后如何更改语言界面?
  19. angular五大服务顺序_双11五折特惠!49.9元抢贵安欢乐世界夜场活动票,五大惊魂大咖点、网红项目女巫塔罗牌占卜,游荡鬼巡游,鬼妆派对~...
  20. 使用go语言编写一个播放器

热门文章

  1. 计算机的硬件技能,计算机的最基础——软硬件
  2. java 单例 读写锁_你用对锁了吗?浅谈 Java “锁” 事
  3. 美术学考计算机,艺术设计专业能跨专业考计算机研究生吗?
  4. java目录实用工具_JAVA 创建文件和文件夹,删除文件和文件夹的实用工具
  5. php 留言板项目 ajax,PHP Ajax留言板
  6. 台式机计算机怎么分割,编辑手把手教程 如何给电脑硬盘分区
  7. @SuppressWarnings使用的正确姿势
  8. Java并发面试宝典,并发相关面试再也难不倒你!
  9. linux网络文件系统包括,Linux文件系统
  10. getLong java_java.lang.Long.getLong()方法实例