[C++基础]C++4个转型操作符——数据类型转换

  • static_cast:静态类型转换。用于基本数据类型之间的转换。 用法:static_cast <typeid> (expression)。 说明:该运算符把expression转换为typeid类型,但没有运行时类型检查来确保转换的安全性。 
  • dynamic_cast:动态类型转换。用在父/子类指针之间的互相转化;。用法:dynamic_cast < type-id > ( expression_r_r )。该运算符把expression_r_r转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression_r_r也必须是一个指针,如果type-id是一个引用,那expression_r_r也必须是一个引用。dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_caststatic_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。用精炼的语言概括,就是专门用于面向对象中的down cast的。但是有三点是前提:第一,必须用于类和子类之间的转换;第二,必须用于指针或引用类型的转换;第三,基类必须有虚函数。
  • const_cast:常量类型转换。把cosntvolatile属性去掉。    
  • reinterpret_cast:重新解释类型转换。用法:reinpreter_cast<type-id> (expression_r_r)。type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
//用法形式都是:xxx_cast<type>(express)
#pragma  once 
#include <string>
#include <iostream>
#include <conio.h>
using namespace std; 
 
//static_cast:基本拥有与C旧式转型相同的威力与意义,以及相同的限制。它用的最多,主要是在基本类型之间的转换
void test1()
{  
	int first=23,second=31;
	double res=(double)first/second; //旧式C语法
	double res2=static_cast<double>(first)/second;//新式C++转型符
	cout<<res<<" "<<res2<<endl;// 0.741935 0.741935
// 	char* str="789";
// 	cout<<static_cast<int>(str)<<endl;//error:无法从char*转换为int
} 
//const_cast:用来去掉表达式中的常量性(constness),常量属性多体现在指针和引用,因为如果没有指针和引用,就不存在不小心修改了不能修改的数据。
void test2()
{
	int num=123;
	const int* pNum=&num;
	//int* pNum1=pNum;//errer:cannot convert from 'const int*' to 'int*'
	int* pNum2=(int*)pNum; //旧式C
	int* pNum3=const_cast<int*>(pNum);//新式C++ const_cast移除常量性
} 
//dynamic_cast:用来执行继承体系中“安全的向下转型或跨系转型动作“,就是子类对象指针转化为父类对象指针。可以利用dynamic_cast将指向base classObject的pointer或reference转型为指向derived classObject的pointer或reference,如果转型失败,会以一个null指针(转换的是pointer的话)或一个exception表现出来(转换的是reference的话)
class B{public:virtual void fun(){cout<<"B.fun()"<<endl;}};
class D1:public B{public:void fun(){cout<<"D1.fun()"<<endl;}void fun2(){cout<<"D1.fun2()"<<endl;}};
class D2:public B{public:void fun(){cout<<"D2.fun()"<<endl;}void fun3(){cout<<"D2.fun3()"<<endl;}};
void test3()
{ 
	//父类指针转换为子类指针时,父类要有虚函数
	B* pb=new D2();
	//pb->fun();//D2.fun()
	D1* pd1=dynamic_cast<D1*>(pb);
	if(pd1)pd1->fun2();//D2.fun()
	D2* pd2=dynamic_cast<D2*>(pb);
	if(pd2)pd2->fun3();//D2.fun3()


	//子类指针转换为父类指针,不需要虚函数
	class CBase{};//基类
	class CDerived : public CBase{};//继承类
	CDerived dc;
	CDerived* dp=&dc;
	CBase* cc1=dp;//老式:子类指针转换为父类指针,即父类指针指向子类对象
	CBase* cb1=dynamic_cast<CBase*>(dp);//使用dynamic_cast将指向继承类的指针转化为指向基类的指针
	printf("point: %d, %d, %d, %d",dp,cc1,cb1,&dc);//它们的地址相同,说明它们在内存中是同一个地址;即子类指针转换为父类指针,父类的地址指向子类的地址,且是相同的。

	CBase& cc2=dc;
	CBase& cb2=dynamic_cast<CBase&>(dc);//使用dynamic_cast将指向继承类的引用转化为指向基类的引用 

} 
//reinterpret_cast:最常用的用途是转化"函数指针"类型
typedef void (*funcPtr)();//funcPtr是个无参数返回值为void型的函数指针类型
int iFunc(){return 0;}//iFunc为一个无参数返回值为int的函数
void func(funcPtr f){}//func函数的参数是一个类型为funcPtr类型的函数指针
void test4()
{ 
	//func(iFunc);//errer:不能将参数1从"int(_cdecl*)(void)"转换为"funcPtr";iFunc函数若是void iFunc(){};就行了
	func(reinterpret_cast<funcPtr>(iFunc));//reinterpret_cast将返回值为int的函数转化为返回值为void的函数。但是传入的参数一定要相同
} 
void test(char t)
{
	cout<<"press key====="<<t<<endl;
	switch (t)
	{ 
	case '1':test1();break;
	case '2':test2();break;
 	case '3':test3();break;
	case '4':test4();break;
	case 27:
	case 'q':exit(0);break;
	default: cout<<"default "<<t<<endl;break;
	}
}
int main()
{
	while(1)
	{
		test(getch());
	} 
	return 0;
}

 

你可能感兴趣的:([C++基础]C++4个转型操作符——数据类型转换)