c++类型转换 const_cast、dynamic_cast、reinterpret_cast、static_cast

const_cast(针对const存在的)

  • c++类型转换,专人做专事,更安全,所有的类型转换语法都相同

  • const_cast<要转换的类型>(要转换的目标)

  • 去掉const属性(提供一个可以修改的接口去操作const属性的变量)

  • 加上const属性(用的比较少)

class A 
{
public:
	A(const char* str) :str(str) {}    //报错:类型不一致改为const char* str也可以
//传入const属性,用const_cast去掉常属性即可
    A(const char* str) :str(const_cast(str)) {}                  	
    //this->str=const_cast(str);
	void print() 
	{
		cout << str << endl;
	}
protected:
	char* str;
};
class B 
{
public:
	B(int num) :num(num) {}
	void print() 
	{
		cout << num << endl;
	}
	int num;
};

int main() 
{
	const int num = 11;    
//去掉const属性
//1.作用普通指针
    //int* pNum = #  报错:类型不一致 可以用const int* pNum = #
	int* pNum = const_cast(&num);
	*pNum = 1134;    //num没有改变 只是提供了可以修改的接口去操作const属性,但是值是没变的
	cout << num << endl;   
//2.操作类中的char*类型指针 const_cast主要用于处理字符串的常属性问题
	A aobject("ILoveyou");    //不加const修饰不能传常量
	aobject.print();
	char str[] = "ILoveyou";  //去掉const属性既可以传变量也可以传常量,保证类型一致性
	A aobject2(str);
	aobject2.print();
//3.操作类指针
	const B* pB = new B(0);
	//pB->print(); 不能调用print() 常对象要调用常成员函数
	B* ppB = const_cast(pB);//直接写报错:需要做类型转换去掉const属性
	ppB->print();
//4.操作常量引用 在引用中也可以用const去做类型转换
	int num;
	const int& pnum = num;               //const引用
//再准备一个引用
    //int& ppnum = pnum;                 //报错:去掉const属性即可
	int& ppnum =const_cast(pnum);  
//5.加上const属性
	int a = 100;
	int* pa = &a;
	const int* ppa = const_cast(pa); //不加也可以赋值成功(隐式转换)
	return 0;
}
/*输出*/

11
ILoveyou
ILoveyou
0

static_cast(做基本数据类型的转换,类似C语言强制类型转换,但不能涉及const_cast类型转换)

  • static_cast<要转换的类型>(要转换的目标)

  • 基本数据类型的转换(类似c语言的强制类型转换)

  • 转换不会影响权限

  • 把空指针转换成目标类型指针

  • 把任何类型的变量转换为void类型

  • 用在类上面的转换( 基类和派生类对象之间的转换 - - - 也就是对象赋值)

  • 进行上行转换(把派生类指针或者引用转换为基类(往上走) 从子到父 指针或者引用转换) 安全

  • 进行下行转换(从父到子 指针或者引用转换) 不安全

  • static_cast不能去掉const,只要涉及const属性的类型转换,必须要用const_cast,c++类型转换,专人做专事

class Parent 
{
public:
	 void print() 
	{
		cout << "parent" << endl;
	}
	void printParent() 
	{
		cout << "parent1" << endl;
	}
};
class Son :public Parent 
{
public:
	 void print()
	{
		cout << "son" << endl;
	}
	void printData() 
	{
		cout << "son2" << endl;
	}
};

int main() 
{
//1.基本数据类型 写和不写是一样的
	char cNum = 'A';
    //int iNum = cNum;                   //把字符转换为整数
	int iNum = static_cast(cNum);
	cout << iNum << endl;
//2.空类型指针  写和不写是一样的
	double* pD = new double;
    //void* pVoid = pD;
	void* pVoid = static_cast(pD);
//3.const类型转换 写和不写是一样的
	int x = 10;
	const int constNum = static_cast(x);
//4.错误用法 不能去掉常属性
	const int xx = 0;
	//int* p = static_cast(&xx);  报错:去掉const 必须用const_cast
//5.从子到父 写和不写是一样的
	Parent* p = new Son;
	p->print();
	Son* pson = new Son;
    //p = pson; 也可以直接赋值
	p = static_cast(pson);
	p->print();
//对象的方式下行转换
    Parent parent;    //构建一个父类对象
    Son son;
    parent = son;     //对象的赋值从子到父
    son = parent;     //父到子不安全:没有与这些操作数匹配的"="运算符
	//son =static_cast(parent);强转报错:不存在用户定义的从"Parent"到"Son"的适当转换
//指针方式的下行转换
	Parent *parent=new Parent;
	Son* son = static_cast(parent);    //可以转换
	son->print();
	son->printData(); //就近原则
	son->printParent();
	return 0;
}

dynamic_cast

  • dynamic_cast<要转换的类型>(要转换的目标)

  • 类似override,可以实时判断是否存在虚函数的类型转换

  • dynamic_cast检查父类中是否存在virutal,不存在 类型转换直接错误 多态的时候使用

  • 上行转换 和 static_cast 一样的

  • 下行转换 从父到子 dynamic_cast 更安全

  • 交叉转换 多继承

c++类型转换 const_cast、dynamic_cast、reinterpret_cast、static_cast_第1张图片

class MM
{
public:
	MM(string mmName = "父类") :mmName(mmName) {}
	virtual void print() { cout << mmName << endl; }
	string mmName;
};
class Girl :public MM
{
public:
	Girl(string gName="子类") :gName(gName) {}
	virtual void print() { cout << gName << endl; }
	void printData() { cout << gName << endl; }
	string gName;
};
class A
{
public:
	virtual void print()
	{
		cout << "A" << endl;
	}
};
class B 
{
public:
	virtual void print()
	{
		cout << "B" << endl;
	}
};
class C :public A, public B
{
public:
	void print()
	{
		cout << "C";
	}
};

int main() 
{
	MM* pM = new MM;
	Girl* pG = new Girl;
//1.上行转换 从子到父
	MM* pSM = static_cast(pG);     //和static_cast一样   
	MM* pDM = dynamic_cast(pG);
	pSM->print();
	pDM->print();
//2.下行转换
	Girl* pSG = static_cast(pM);  //无virtual 不会报错 运行会中断
	Girl* pDG = dynamic_cast(pM); //运行时dynamic_cast的操作数必须包含多态类类型
	pSG->print();                        //无virtual 运行会中断
	//下行转换,调用子类中父类没有函数会报错
	//pSG->printData(); 
	if (pDG != nullptr)                  //转换失败返回空
	{
		pDG->print();
	}
//3.交叉转换   A对象的指针通过C类的对象初始化,B类的指针也可以间接通过A的指针初始化
	A* a = new C;               
    B* b = a;                    //不转换报错:"A"类型的值不能用于初始化"B"类型的实体
    B* b = (B*)a;
	B* b = dynamic_cast(a);  //C类对象既可以赋值给A,也可以赋值给B,A可以赋值给B
	b->print();                  //两个父类指针都可以通过子类对象初始化
	return 0;
}

/*输出*/

子类
子类
父类
C

reinterpret_cast

  • 把指针转换为数字,再把数字转换为指针,并且能够保持指针的作用

int Max(int a, int b) 
{
	return  a > b ? a : b;
}
int main() 
{
	int num = reinterpret_cast(Max);                //把函数指针转换为数字
	cout << num << endl;
	cout << Max << endl;
	auto pMax = reinterpret_cast(num); //数字又可以转换为函数指针
	cout << pMax(1, 2) << endl;
    cout << reinterpret_cast(num)(1, 2) << endl;
	return 0;
}

/*输出*/

15601979(10进制数)
00EE1138(16进制数)
2
2

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