C++中的类型转换

文章目录

    • 1.C++的强制类型转换
    • 2. static_cast
      • 2.1 基本数据类型的转换
      • 2.2 父类与子类类型指针转换
    • 3.dynamic_cast
      • 3.1 指针类型
      • 3.2 引用类型
    • 4.const_cast
    • 5. reinterpret_cast

1.C++的强制类型转换

在c语言的基础上,C++新增加了四种强制类型转换:

static_cast<new_type>(expression)
dynamic_cast<new_type>(expression) 
const_cast<new_type>(expression) 
reinterpret_cast<new_type> (expression)

其中,new_type为目标数据类型,variable为变量或者表达式

2. static_cast

static_cast用于以下类型转换,static_cast在类型转换时,在编译期间会对类型进行检查,运行时不会检查类型转换的安全性

  • 基本数据类型之间的转换:如enum转换为int,int转换为char

  • 将空指针转换为目标类型的空指针

  • 将任何类型的表达式都转换为void类型

  • non-const变量转换为const变量

  • static_cast还可以转换对象的指针类型,但它不进行运行时类型检查,如用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换

    ​ 1.将基类转换为派生类:安全

    ​ 2.派生类转换为基类:不安全

注意:static_cast不能移掉expression中的const,volatile以及_unaligned属性

2.1 基本数据类型的转换

enum Week
{
	Monday = 1,
	Tuesday,
	Wednesday,
	Thursday,
	Friday,
	Saturday,
	Sunday
};
Week noday = static_cast<Week>(7) //sucess
Week noday = static_cast<Week>(8) //error

int i = 10;
char c = static_cast<char>(i);//正确,int转换为char

int *pI = NULL;
char *cI = static_cast<void*>(pI);//将int类型空指针转换为char空指针

int i = 10;
const int j = static_cast<const int>(i);//正确,将int型数据转换成const int型数据

const int i = 20;
int ii = static_cast<int>(i);//编译错误,static_cast不能转换掉i的const属性

2.2 父类与子类类型指针转换

class B{};
class C : public B{};

voif f(B *pb,C *pC)
{
   C* pC1 = static_cast<C*>(pb); //父类转子类,不安全
   B* pB1 = static_cast<B*>(pC); //安全,子类转父类
}

上面的第一个类型转换是不安全的。比如,一旦使用pC1调用了一个子类C有而父类B没有的方法,程序就会因越界访问而崩溃。

3.dynamic_cast

dynamic_cast是将一个基类对象指针或者引用转换到继承类类指针或者引用,dynamic_cast用来检查两者是否有继承关系,因此实际上只接受基于类对象的指针或者引用的转换,转换格式为:

dynamic_cast<new_type*>(expression):new_type必须为有效指针
dynamic_cast<new_type&>(expression):new_type必须为左值
dynamic_cast<new_type&&>(expression):new_type必须为右值

如果 new_type是类指针类型,那么expression也必须是一个指针,如果 new_type 是一个引用,那么 expression 也必须是一个引用。dynamic_cast可以在执行期决定真正的类型。在下行转换时具有类型检查的功能,比static_cast是安全的,如果下行转换是安全的(也就说,如果基类指针或者引用指向一个派生类对象)这个运算符会传回适当转型过的指针。如果 下行转换不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。

3.1 指针类型

基类中必须包含至少一个虚函数,而static_cast没有这个限制

class B
{
public:
	int m_i;
	virtual void f();//基类必须有一个虚函数
};

class C:public B
{
public:
	char *m_Str[100];
}

void(B* pb,C *pc)
{
	if(B *pB = dynamic_cast(pc)){
  	    //使用pB指向的C对象  
	}
	else{
	 pB = dynamic_cast(pB)
  	    //使用pb指向的B对象  
	}
}

在上面的代码中,在if语句定义pB,可以完成类型转换和安全性检查两项任务

3.2 引用类型

因为不存在所谓空引用,所以引用类型的dynamic_cast转换与指针类型不同,在引用转换失败时,会抛出std::bad_cast异常,该异常定义在头文件typeinfo中。

void f(const C &c){
 try{
   const B &b = dynamic_cast<const C&>(c);  
   //使用b引用的C对象
 }
 catch(std::bad_cast){
   //处理类型转换失败的情况
 }
}

4.const_cast

const_cast,用于修改类型的const或volatile属性,主要用于去掉const属性,该运算符用来修改类型的const(唯一有此能力的C+±style转型操作符)或volatile属性。除了const 或volatile修饰之外, new_type和expression的类型是一样的。

const_cast < new_type > ( expression )

主要应用场景为:

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

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

  3. const_cast一般用于修改底指针,如const char *p形式。

const int i = 10;
int *pi = const_cast(&i);//去掉const常量的const属性

const int i = 20;i
int &h = const_cast(i);//去掉const引用const属性

const char *str = "hello";
char *h = const_cast(str);//去掉const指针const属性

5. reinterpret_cast

reinterpret_cast < new_type > ( expression )

new_type必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值),它是这四种转换运算符中最不安全的,它主要适用于依赖底层实现的编程技术,因为不系统一个类型存储的字节可能是不一样的,所以具有不可移植性、对平台的依赖性强。

代码示例:

#include 
using namespace std;

class Data
{
public:
	short a;
	short b;
};

void delete_ptr(void *p)
{
    if(p != nullptr)
    {
        delete p; 
        p=nullptr;
    }
}

int main()
{

	long value = 0xAAAABBBB;
	Data *pData = reinterpret_cast<Data*>(&value);
	cout << hex << pData->a << endl;
	cout << hex << pData->b << endl;
	// 不需要释放指针pData的空间,它的地址和变量value相同,会自动释放掉
	// delete_ptr(pData);
}
结果为:
BBBB
AAAA

你可能感兴趣的:(C++基础知识,c++,开发语言)