【C++知识点】类型转换

C/C++知识点

C++类型转换

旧式转型 C 风格的强制类型:

TYPE b = (TYPE) a

例如:

int i = 48;	
char c = (char) i;

新式转型 C++ 风格的类型转换提供了 4 种类型转换操作符来应对不同场合的应用。

TYPE b = 类型操作符 ( a )

类型操作符 = static_cast | reinterpreter_cast | dynamic_cast | const_cast

static_cast

静态类型转换(斯文的劝导,温柔的转换),类似于 C 语言中的隐式转换,如 int 转换成 char 。

主要用法:

  • 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。上行指针或引用(派生类到基类)转换安全,下行(基类到派生类)转换不安全。

  • 用于基本数据类型之间的转换,如把 int 转换成 char ,把 int 转换成 enum 。这种转换的安全性也要开发人员来保证。

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

  • 把任何类型的表达式转换成 void 类型。

#include <iostream>

using namespace std;

class Animal {
public:
	virtual void cry() = 0;
};

class Cat :public Animal
{
public:
	void cry()
	{
		cout << "喵喵瞄" << endl;
	}
};

class Dog :public Animal
{
public:
	void cry()
	{
		cout << "汪汪汪" << endl;
	}
};
用法一:父子类之间的类型转换
Dog* dog1 = new Dog();
Animal* a1 = static_cast<Animal*>(dog1); //子类的指针转型到父类指针

Dog* dog1_1 = static_cast<Dog*>(a1);     //父类的指针转型到子类的指针
//父子到子类,有风险,虽然下面这句不会报错,但是狗类转换成猫类是完全错误的做法
Cat* cat1 = static_cast<Cat*>(a1);

Dog dog2;
Animal& a2 = static_cast<Animal&>(dog2); //子类的引用转型到父类的引用
Dog& dog2_2 = static_cast<Dog&>(a2);     //父类到子类引用
用法二:基本类型的转换
int  kk = 234;
char cc = static_cast<char>(kk);
用法三:把空指针转换成目标类型的空指针
int* p = static_cast<int*>(NULL);
Dog* dp = static_cast<Dog*>(NULL);
用法四:把任何类型的表达式转换成 void 类型
int* pi = new int[10];
void* vp = static_cast<void*>(pi);

reinterpret_cast

重新解释类型(挂羊头,卖狗肉))不同类型间的互转,数值与指针间的互转。

用法: TYPE b = reinterpret_cast ( a )

TYPE 必须是一个指针、引用、算术类型、函数指针

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

#include <iostream>

using namespace std;

class Animal {
public:
	void cry() {
		cout << "动物叫" << endl;
	}
};

class Cat :public Animal
{
public:
	void cry()
	{
		cout << "喵喵瞄" << endl;
	}

};

class Dog :public Animal
{
public:
	void cry()
	{
		cout << "汪汪汪" << endl;
	}

};
用法一:数值与指针之间的转换
int* p = reinterpret_cast<int*>(0x99999);
int val = reinterpret_cast<int>(p);
用法二:不同类型指针和引用之间的转换
Dog  dog1;
Animal* a1 = &dog1;
a1->cry();	//动物叫

Dog* dog1_p = reinterpret_cast<Dog*>(a1);
Dog* dog2_p = static_cast<Dog*>(a1);   //如果能用static_cast ,static_cast 优先
dog1_p->cry();	//汪汪汪
dog2_p->cry();	//汪汪汪

//Cat* cat1_p = static_cast<Cat*>(a1);	//输出喵喵喵
//Cat* cat2_p = static_cast<Cat*>(dog1_p); //报错,不同类型指针转换不能使用static_cast
Cat* cat2_p = reinterpret_cast<Cat*>(dog1_p);	//但是这个强制转换不会报错
cat2_p->cry();	//喵喵喵

Animal& a2 = dog1;
Dog& dog3 = reinterpret_cast<Dog&>(a2);//引用强转用法

dynamic_cast

动态类型转换

  • 将一个基类对象指针 cast 到继承类指针,dynamic_cast 会根据基类指针是否真正指向继承类指针来做相应处理。失败返回 null ,成功返回正常 cast 后的对象指针。

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

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

#include <iostream>

using namespace std;

class Animal {
public:
	virtual void cry() = 0;
};

class Cat :public Animal
{
public:
	void cry()
	{
		cout << "喵喵瞄" << endl;
	}

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

class Dog :public Animal
{
public:
	void cry()
	{
		cout << "汪汪汪" << endl;
	}

	void play()
	{
		cout << "溜达溜达" << endl;
	}
};
用法一:指针类型转换
void animalPlay(Animal* animal) {
	animal->cry();

	Dog* pDog = dynamic_cast<Dog*>(animal);
	if (pDog) {
		pDog->play();
	}
	else { //pDog == NULL
		cout << "不是狗,别骗我!" << endl;
	}

	Cat* pCat = dynamic_cast<Cat*>(animal);
	if (pCat) {
		pCat->play();
	}
	else { //pDog == NULL
		cout << "不是猫,别骗我!" << endl;
	}
}

int main() {
	Dog* dog1 = new Dog();
	Animal* a1 = dog1;
	animalPlay(a1);

	cout << endl;

	Cat* cat1 = new Cat();
	Animal* a2 = cat1;
	animalPlay(a2);
    
	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SLQT3wtb-1659797530057)(C++常见知识点及问题.assets/image-20220801103058966.png)]

用法二:引用类型转换
void animalPlay(Animal& animal) {
	animal.cry();

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

	try {
		Cat& pCat = dynamic_cast<Cat&>(animal);
		pCat.play();
	}
	catch (std::bad_cast bc) {
		cout << "不是猫,那应该是上面的狗" << endl;
	}
}

int main() {
	Dog* dog1 = new Dog();
	Dog dog2;
	animalPlay(dog2);

	cout << endl;

	Cat* cat1 = new Cat();
	Cat cat2;
	animalPlay(cat2);

	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HZPIDveE-1659797530059)(C++常见知识点及问题.assets/image-20220801103246366.png)]

const_cast

去掉 const 属性。(仅针对于指针和引用)

#include <iostream>

using namespace std;

void demo(const char* p)
{
	//对指针去掉cost 重新赋值
	char* p1 = const_cast<char *>(p);
	p1[0] = 'A';

	//直接去掉const修改
	const_cast<char*>(p)[1] = 'B';
	
	cout << p << endl;

}

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

int main(void)
{
	//字符串数组
	//char p[] = "12345678";
	//demo(p);  //合情合理

	//常量字符串不能去掉const 修改
	//警告: 在去掉常量限定符之前,保证指针所指向的内存能够修改,不能修改则会引起异常。
	const char* cp = "987654321";
	demo(cp);

	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 ++大牛建议: 一般情况下,不建议进行类型转换,避免进行类型转换。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值