C++类型转换

C++类型转换

旧式转换类型
C风格的强制类型转换: Type B = (Type)a;
例:
int i=48;
char n = (char) i;

新式类型转换C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用
格式:
Type b = 类型操作符(a);
类型操作符有: static_cast, reinterpret_cast, dynamic_cast, const_cast;

1.static_cast

静态类型转换(斯文的劝导,温柔的转换), 如 int 转换成char;
主要用法:
1.用于类层次结构中父类和子类之间指针或引用的转换,上行指针或引用(子类到父类)转换安全,下行不安全;
2.用于基本数据类型之间的转换,如把int转换成char, 把int转换成enum,这样转换的安全性也要开发者来保证;
3.把空指针转换成目标类型的空指针;
4.把任何类型的表达式转换成void类型;

#include <iostream>

using namespace std;

//构建一个动物抽象类
class Animal {
public:
	//纯虚函数
	virtual void cry() = 0;
};

//构造一个基于Animal类的Cat子类,继承方式为公有
class Cat :public Animal {
public:
	virtual void cry() {
		cout << "喵...喵...喵...!" << endl;
	}
};

//构造一个基于Animal类的Dog子类,继承方式为公有
class Dog :public Animal {
public:
	virtual void cry() {
		cout << "汪...汪...汪...!" << endl;
	}
};

int main(void) {

	//第一种情况:父类和子类之间的类型转换
	Dog* dog_1 = new Dog();
	Animal* a_1 = static_cast<Animal*>(dog_1);//子类的指针转换类型到父类指针

	Dog* dog_2 = static_cast<Dog*>(a_1);//父类的指针转换类型到子类的指针
	Cat* cat_1 = static_cast<Cat*>(a_1);//父类到子类,有风险,这样是不行的

	Dog dog_3;
	Animal& a_2 = static_cast<Animal&>(dog_3);//子类的引用转换类型到父类的引用
	Dog& dog_4 = static_cast<Dog&>(a_2);//父类到子类引用

	//第二种:基本类型转换
	int i_n = 55;
	char c_k = static_cast<char>(i_n);

	//第三种:把空指针转换成目标类型的空指针
	int* p = static_cast<int*>(NULL);
	Dog* p_dog = static_cast<Dog*>(NULL);

	//第四种:把任何类型的表达式转换成void类型
	int* i_ptr = new int[10];
	void* v_ptr = static_cast<void*>(i_ptr);
	v_ptr = i_ptr;//结果同上


	system("pause");
	return 0;
}

2.reinterpret_cast

重新解释类型(挂羊头,卖狗肉)不同类型间的互转,数值与指针间的互转;
用法:
Type b = reinterpret_cast(a);
Type必须是一个指针,引用,算术类型,函数指针;

注意:
滥用reinterpret_cast运算符可能很容易带来风险,除非所需转换本身是低级的,否则应使用其他强制转换运算符之一;

#include <iostream>

using namespace std;

//构建一个动物类
class Animal {
public:
	//纯虚函数
	virtual void cry() {
		cout << "动物叫...!" << endl;
	}
};

//构造一个基于Animal类的Cat子类,继承方式为公有
class Cat :public Animal {
public:
	virtual void cry() {
		cout << "喵...喵...喵...!" << endl;
	}
};

//构造一个基于Animal类的Dog子类,继承方式为公有
class Dog :public Animal {
public:
	virtual void cry() {
		cout << "汪...汪...汪...!" << endl;
	}
};

int main(void) {

	//用法一: 数值与指针之间的转换
	int* i_ptr = reinterpret_cast<int*>(999);//获得一个地址(指针变量)
	int val = reinterpret_cast<int>(i_ptr);//获取一个数值

	//用法二:不同类型指针和引用之间的转换
	Dog dog;
	Animal* a = &dog;
	a->cry();

	Dog* dog1_p = reinterpret_cast<Dog*>(a);
	Dog* dog2_p = static_cast<Dog*>(a);//如果能用static_cast,优先使用
	//Cat* c_p = static_cast<Cat*>(dog1_p);error! 不同类型指针转换不能使用static_cast

	Cat* c2_ptr = reinterpret_cast<Cat*>(dog1_p);//reinterprent_cast可以进行不同类型之间的转换
	Animal& a2 = dog;
	Dog& dog2 = reinterpret_cast<Dog&>(a2);//引用强转用法

	dog1_p->cry();
	a2.cry();
	c2_ptr->cry();

	system("pause");
	return 0;
}

在这里插入图片描述

dynamic_cast

动态类型转换:
1.将一个父类对象指针cast到继承类指针,dynamic_cast 会根据父类指针是否真正指向继承类的指针来做相应处理,失败返回NULL,成功返回正常cast后的对象指针;

2.将一个父类对象引用cast继承类对象,dynamic_cast 会根据父类对象是否真正属于继承类来做相应的处理.失败抛出异常bad_cast;

注意:
dynamic_cast在将父类cast到子类时,父类必须要有虚函数;

#include <iostream>

using namespace std;

//构建一个动物类
class Animal {
public:
	//纯虚函数
	virtual void cry() = 0;
};

//构造一个基于Animal类的Cat子类,继承方式为公有
class Cat :public Animal {
public:
	virtual void cry() {
		cout << "喵...喵...喵...!" << endl;
	}

	void play() {
		cout << "爬树...!" << endl;
	}
};

//构造一个基于Animal类的Dog子类,继承方式为公有
class Dog :public Animal {
public:
	virtual void cry() {
		cout << "汪...汪...汪...!" << endl;
	}

	void play() {
		cout << "溜达...!" << endl;
	}
};

void animaplay(Animal& animal) {
	animal.cry();

	try
	{
		Dog& dog_ptr = dynamic_cast<Dog&>(animal);
		dog_ptr.play();
	}
	catch (bad_cast bc)
	{
		cout << "不是狗,那应该是猫!" << endl;
	}

	try
	{
		Cat& cat_ptr = dynamic_cast<Cat&>(animal);
		cat_ptr.play();
	}
	catch (bad_cast bc)
	{
		cout << "不是猫,那应该是狗!" << endl;
	}
}

int main(void) {

	Dog* dog_ptr = new Dog();
	Animal* a_ptr = dog_ptr;

	//animaplay(*a_ptr);

	Dog dog_ptr2;
	animaplay(dog_ptr2);

	Cat* cat_ptr2 = new Cat();
	Animal* a2 = cat_ptr2;

	//animaplay(*a2);
	
	Cat cat_ptr3;
	animaplay(cat_ptr3);

	system("pause");
	return 0;
}

在这里插入图片描述

const_cast

去除const 属性,(仅针对于指针和引用)

#include <iostream>

using namespace std;

void demo(const char* ptr) {
	//对指针去除const重新赋值
	//char* ptr1 = const_cast<char*>(ptr);
	//ptr1[0] = 'a';

	//直接去除const修改
	const_cast<char*>(ptr)[0] = 'A';

	cout << ptr << endl;
}

void demo(const int p) {
	int pt = p;
	//const_cast<int>(p) = 888; error! 不能对非指针和引用进行const转换
	cout << p << endl;
}

int main(void) {

	//字符串数组
	//char ctr[] = "123";
	//demo(ctr);//正常使用

	//常量字符串不能去除const修饰
	//警告: 在去除常量限定符之前, 保证指针所指的内存是可以修改的,不可以修改则会引起异常
	const char* c_ptr = "9527";
	demo(c_ptr);
	
	system("pause");
	return 0;
}

类型转换使用建议
1.static_cast静态类型转换,编译的时c++编译器会做编译时的类型检查;隐式转换;
基本类型转换,父子类之间合理转换;

2.若不同类型之间,进行强制类型转换,用reinterpret_cast<>() 进行重新解释;

建 议:
C语言中 能隐式类型转换的,在c++中可用 static_cast<>()进行类型转换。因C++编译器在编译检查一般都能通过;C语言中不能隐式类型转换的,在c++中可以用 reinterpret_cast<>() 进行强制类型解释。

总结:
static_cast<>()和reinterpret_cast<>() 基本上把C语言中的 强制类型转换给覆盖,注意reinterpret_cast<>()很难保证移植性。

3.dynamic_cast<>(),动态类型转换,安全的虚基类和子类之间转换;运行时类型检查;

4.const_cast<>(),去除变量的只读属性 ;

最后的忠告:
程序员必须清楚的知道: 要转的变量,类型转换前是什么类型,类型转换 后是什么类型,转换后有什么后果。

C++大牛建议:
一般情况下,不建议进行类型转换;避免进行类型转;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值