C/C++ — 浅析C++的强制类型转换

原创 2017年09月09日 15:23:20

C++的强制类型转换 

                                                                                                                                                            



说起强制类型转换大家都很熟悉,相信很多学习完C++的朋友还在使用C语言的强制类型的方式 (类型)变量. 

C++其实也具有自己的一套强制类型转换它们分明是:static_cast  reinterpret_cast  const_cast  dynamic_cast四种

类型.那么肯定会有人好奇C++是不是闲,C语言的强制类型用的舒舒服服的,为什么要新推出来这几个?

新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++中风格是static_cast<typ

e>。C++风的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知

一个强制转换的目


static_cast

                                                                               


static_cast用于非多态类型的转换(静态转换),任何标准转换都可以用它,但它不能用于两个不相关的类型进行转换.


何为不相关类型? 比如int 和 double char short就是相关类型. 和int*就是不相关类型.


我们来看一看static_cast的用法.  例如,通过将一个运算对象强制转换成double类型就能使表达式执行浮点数除法:


  double slope = static_cast<double>(j) / i;


static_cast需要把一个较大的算术类型赋值给较小的类型时,static_cast非常有用。此时,强制类型转换告诉程序

的读者和编译器:我们知道并且不在乎潜在的精度损失。一般来说,如果编译器发现一个的算术类型试图赋值给较小的

类型,就会给出警告信息;但是当我们执行了显式的类型转换后,警告信息就会被关闭了。




reinterpret_cast

                                                                       


reinterpret_cast有着和C风格的强制转换同样的能力。它可以转化任何内置的数据类型为其他任何的数据类型,也可以转化

任何指针类型为其他的类型。它甚至可以转化内置的数据类型为指针,无须考虑类型安全或者常量的情形。不到万不得已绝对用。


因为reinterpret_cast是一个蛮bug的操作,下面我来演示一下.

typedef void (* FUNC)();
int DoSomething (int i)
{
     cout<<"DoSomething" <<endl;
     return 0;
}
void Test ()
{
     // reinterpret_cast可以编译器以FUNC的定义方式去看待 DoSomething函数
     // 所以非常的BUG,下面转换函数指针的代码是不可移植的,所以不建议这样用
     // C++不保证所有的函数指针都被一样的使用,所以这样用有时会产生不确定的结果
     FUNC f = reinterpret_cast< FUNC>(DoSomething );
     f();
}

当你这样运行的时候,你会发现通过函数指针没有传参数调用这个有参数的函数居然可以调用,这就很尴尬了,所以我告诉你不到万

不得已就不要使用reinterpret_cast



const_cast

                                                                             


对于将常量对象转化为非常量对象的行为,我们一般称之为“去掉const性质”。一旦我们去掉了某个对象的const性质

,编译器就不再阻止我们对该对象进行写操作了。如果对象本身不是一个常量,使用强制类型转换获得写权限是合法

行为。然而如果对象是一个常量,再使用const_cast执行写操作就会产生未定义的后果。

举个例子:

#include<iostream>
#include<Windows.h>
#include<assert.h>

using namespace std;

int main()
{
	const int a = 2;
	int *p = const_cast<int*>(&a);
	*p = 3;
	cout << a << endl;
	system("pause");
	return 0;
}

我们有理由的认为在内存当中a的值被修改为3,但是结果呢? 我们来看一看



这不科学啊?? 我们再打开监视窗口看一下a的值.



我们都知道监视窗口看到的都是从内存当中拿到的,但是为什么内存当中为3,打印出来就是2呢? 我来解释一下.

C++编译器具有优化功能,当你定一个const的常量的时候,系统觉得它不会被改变了,于是做一个优化把该常量存到寄

存器当中,下次访问的过程更快速一点. 所以当显示窗口读取数据的时候,他会直接去寄存器当中读取数据.而不是去

内存,所以导致我们明明该掉了a的值,却打印不出来,但是如何解决这个问题呢??

c++有一个关键字: volatile 该关键字的作用防止编译器优化,这个时候要输出a就会老老实实的回内存去查看.

#include<iostream>
#include<Windows.h>
#include<assert.h>

using namespace std;

int main()
{
	volatile const int a = 2;
	int *p = const_cast<int*>(&a);
	*p = 3;
	cout << a << endl;
	system("pause");
	return 0;
}


dynamic_cast

                                                                        

前三种的强制类型转换,他们能做到的C语言的强制类型转换也大多能做到,最后一种C语言的强制类型转换就没


有办法了.在类的转换时,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进行下


行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。当用于多态类型时,它允许任意的隐式类


型转换以及相反过程. 不过,与static_cast不同,在后一种情况里(注:即隐式转换的相反过程),dynamic_cast


会检查操作是否有效. 也就是说, 它会检查转换是否会返回一个被请求的有效的完整对象。检测在运行时进行. 


如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL. 对于引用 类型,会抛出bad_cast异常


你说这个强转有啥用,其实对于我这种菜鸟还真的没用过,不过我知道一个问题可以使用这样的方法解决. 给你两


个类让你分辨那个是子类那个是父类,我们来看看是如何解决的.


#include<iostream>
#include<Windows.h>
#include<assert.h>

using namespace std;

class AA
{
public:

	virtual void fun1()
	{
		cout << "hehe" << endl;
	}
public:
	int a;
};

class BB :public AA
{
public:

	virtual void fun1()
	{
		cout << "heh2e" << endl;
	}
public:
	int c;
};
int main()
{
	AA* q = new AA();
	BB* p = new BB();
	AA* a;
	BB* b;

	b = dynamic_cast<BB*>(q);
	if (b == NULL)
	{
		cout << "AA为基类" << endl;
	}
	else{
		cout << "AA为子类" << endl;
	}

	a = dynamic_cast<AA*>(p);
	if (a == NULL)
	{
		cout << "BB为基类" << endl;
	}
	else
	{
		cout << "BB为子类" << endl;
	}
	system("pause");
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

java提高篇(十)-----强制类型转换

在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换。        在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类...

滥用强制类型转换的缺点

这是C++为什么要引入四个转换符的原因。 尽量使用C++风格的类型转换     仔细想想地位卑贱的类型转换功能(cast),其在程序设计中的地位就象goto语句一样令人鄙视。但是它还不是无法令...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

浅析TCP通信原理

TCP通信 TCP是面向连接的通信,所以在通信之前,客户端与服务器端必须通过三次握手建立连接,然后在通信完毕,还要通过四次挥手断开连接。 (一)相关函数 1.创建套接字 domai...

TCP协议疑难杂症全景解析

说明:1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人。因...
  • dog250
  • dog250
  • 2011-07-17 19:28
  • 65280

SYNPROXY抵御DDoS攻击的原理和优化

序又到了周末,我又要必须写点什么了…  周末依然加班,感谢周末上班平日休息的老婆分担了几乎所有家务,一切依然…然而这些对我来讲都不是个事儿,事实上我是希望取消一切节假日和周末的,所谓的周末和节假日是我...
  • dog250
  • dog250
  • 2017-09-10 18:25
  • 2465

【C/C++和指针】深度剖析----强制类型转换(一)

一,强制类型转换   当操作数的类型不同,而且不属于基本数据类型时,经常需要强制类型转换,将操作数转化为所需要的类型。强制类型转换具有两种形式,称为显式强制转换和隐式强制类型转换。强制类型转...

c/c++强制类型转换

c/c++强制类型转换 被问到dynamic_cast与static_cast的区别,回答不出来,狂郁闷,语法还得好好加强。 zz   Q:什么是C风格转换?什么是stat...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)