中国大学MOOC程序设计与算法(三):C++ 面向对象程序设计 第十周 C++11新特性和C++高级主题 笔记 之 强制类型转换

第十周 C++11新特性和C++高级主题
1.C++11新特性(一)
2.C++11新特性(二)
3.强制类型转换
4.异常处理

3.强制类型转换

四种运算符可以实现强制类型转换:static_cast、reinterpret_cast、const_cast和dynamic_cast。

过去也有强制类型转换到额方式,比如(int)a,int(a),(A)a。问题是这些转换方式对转换的风险是不分类的,而且debug的时候如果要找强制类型转换的地方,需要每一种类型都搜索一下。但是如果用这四种新的强制类型转换关键字,不仅可以按照风险将程序中的强制类型转换分类,而且debug的时候只需要搜索这四个关键字、甚至只搜索"_cast"zh这个关键字就可以了。

(1)static_cast 静态转换

static_cast用来进用行比较“自然”和***低风险的转换***,比如整型和实数型、字符型之间互相转换。
static_cast***不能来在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,也不能用于不同类型的引用之间的转换。***
用法:static_cast,static_cast等。

#include 
using namespace std;
class A
{
	public:
		operator int() { return 1; }//重载了"int()"这个类型转换运算符,注意类型转换运算符被重载时是不需要写返回值的,重载的类型是什么,就自动返回什么类型。
		operator char * (){ return NULL; }//重载了"char * ()"这个类型转换运算符
};
int main()
{
	A a;
	int n; char * p = "New Dragon Inn";
	n = static_cast<int>(3.14); // n 的值变为 3
	n = static_cast<int>(a); //调用a.operator int, n的值变为 1
	p = static_cast<char*>(a);//调用a.operator int *,p的值变为 NULL
	n = static_cast<int> (p);//编译错误,static_cast不能将指针转换成整型
	p = static_cast<char*>(n);//编译错误,static_cast不能将整型转换成指针
	return 0;
}

(2)reinterpret_cast

reinterpret_cast用来进行***各种不同类型的指针之间的转换、不同类型的引用之间转换、以及指针和能容纳得下指针的整数类型之间的转换***。转换的时候,执行的是逐个比特拷贝的操作,将被转换目标的每一个内存比特都拷贝到目的地中去。。

#include 
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 引用 a,int r只有四个字节,所以其实只是引用了a的前四个字节,也就只是i而已。
	r = 200; //把 a.i 变成了 200
	cout << a.i << "," << a.j << endl; // 输出 200,100
	int n = 300;
	A * pa = reinterpret_cast<A*> ( & n); //强行让 pa 指向 n
	pa->i = 400; // n 变成 400
	pa->j = 500; //此条语句不安全,很可能导致程序崩溃
	cout << n << endl; // 输出 400
	long long la = 0x12345678abcdLL;
	pa = reinterpret_cast<A*>(la);
	// la太长,只取低32位0x5678abcd拷贝给pa
	unsigned int u = reinterpret_cast<unsigned int>(pa);
	//pa逐个比特拷贝到u
	cout << hex << u << endl; //输出 5678abcd
	typedef void (* PF1) (int);
	typedef int (* PF2) (int,char *);
	PF1 pf1; PF2 pf2;
	pf2 = reinterpret_cast<PF2>(pf1);
	//两个不同类型的函数指针之间可以互相转换
}
输出结果:
200,100
400
5678abcd

(3)const_cast

用来进行***去除const属性***的转换。将const引用转换成同类型的非const引用,将const指针转换为同类型的非const指针时用它。例如:

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

(4)dynamic_cast 基类指针转换为派生类指针

基类指针被转换成派生类指针时,如果访问派生类的成员,会出错。dynamic_cast专门用于将多态基类的指针或引用,强制转换为派生类的指针或引用,而且能够检查转换的安全性。对于不安全的指针转换,转换结果返回NULL指针。
多态基类是包含虚函数的基类。
dynamic_cast不能用于将非多态基类的指针或引用,强制转换为派生类的指针或引用

#include 
#include 
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 不会为NULL
		cout << "unsafe dynamic_cast2" << endl; //不会执行
	return 0;
}
输出结果:
unsafe dynamic_cast1

dynamic_cast还可以实现基类引用到派生类引用的转换,并且还可以判断是否安全。

Derived & r = dynamic_cast<Derived&>(b);//b是基类对象,也可以被看做基类的引用。

那该如何判断该转换是否安全呢?
答案:不安全则抛出异常,下一节讲异常处理。

这一节我都不太能彻底理解???

你可能感兴趣的:(c++,强制类型转换,c++11)