C++类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast)


类型转换(cast):将一种数据类型转换为另一种数据类型。

标准C++提供显式转换的语法,基于模板技术实现,以替代C风格的类型转换,可更好地控制强制转换的过程,允许控制各种不同类型的强制转换,且能够清晰地表明作用

注:C++实际开发中,应尽可能少地使用类型转换,除非用于解决非常特殊的问题,如stringconst char *之间的类型转换。应考虑重新设计数据结构,避免过多的类型转换。


1 静态类型转换(static_cast)

语法目标数据类型 变量/对象 = static_cast<目标数据类型>(原变量/对象);

作用
(1)用于内置基本数据类型之间的转换。如int和char类型之间的互相转换,安全性需开发人员保证

(2)用于类层次结构父类子类之间指针或引用的转换
上行转换:子类的指针或引用转换为父类表示,安全
下行转换:父类的指针或引用转换为子类表示,由于没有动态类型检查可能导致指针寻址越界不安全

注1:子类对象占用的内存空间大于父类对象,因此子类的指针或引用可访问的内存范围更大。
向上转换(子类转化为父类表示)时是安全的
向下转换(父类转化为子类表示)时是不安全的
注2:非关联类之间不可进行静态类型转换,否则编译器报错:类型转换无效

示例:静态类型转换

#include <iostream>
using namespace std;

//静态类型转换-内置基本数据类型的转换
void func1() {
    
    
	char ch = 'a';
	double d = static_cast<double>(ch);

	cout << d << endl;	//97
}

class Father {
    
    };
class Son : public Father {
    
    };	//继承
class Other {
    
    };	//非关联类

//静态类型转换-继承中父子类指针的转换
void func2() {
    
    
	Father* father = NULL;
	//向下转换-不安全
	Son* son = static_cast<Son*>(father);

	//向上转换-安全
	Father* f = static_cast<Father*>(son);

	//无效转换:非关系类之间不可进行静态类型转换
	//Other* other = static_cast<Other*>(father);	//报错:类型转换无效
}

//静态类型转换-继承中父子类引用的转换
void func3() {
    
    
	Father f;
	Son s;

	Father& father = f;
	Son& son = s;

	//向下转换-不安全
	Son& s1 = static_cast<Son&>(father);

	//向上转换-安全
	Father& f1 = static_cast<Father&>(son);

	//无效转换:非关系类之间不可进行静态类型转换
	//Other& other = static_cast<Other&>(father);	//报错:类型转换无效
}

2 动态类型转换(dynamic_cast)

语法目标数据类型 对象 = dynamic_cast<目标数据类型>(原对象);

作用
(1)不支持内置基本数据类型之间的转换,否则编译器报错:dynamic_cast中的类型必须是指向完整类类型或 void* 的指针或引用

注1:动态类型转换dynamic_cast会规避不安全的情况,存在安全风险时,不允许类型转换
注2:动态类型转换dynamic_cast不支持内置基本数据类型之间的转换。
内置基本数据类型转换时,可能存在精度丢失(如double类型转换为float类型)、数据截断(如4字节的int类型转换为1字节的char类型)等安全隐患。

(2)主要用于类层次结构父类子类之间指针或引用的转换,如多态调用上行转换不支持下行转换的不安全情况。
多态调用:父类指针或引用指向子类对象,发生多态时,编译器认为类型转换总是安全的支持多态调用时的下行转换。【支持转换】
上行转换:子类的指针或引用转换为父类表示,安全,与static_cast效果相同。【支持转换】
下行转换:父类的指针或引用转换为子类表示,不安全dynamic_cast具有动态类型检查功能,不支持下行转换,否则编译器报错:运行时dynamic_cast的操作数必须包含多态类类型。【不支持转换】

示例:动态类型转换

#include <iostream>
using namespace std;

//动态类型转换-不支持内置基本数据类型的转换
void func1() {
    
    
	char ch = 'a';
	//报错:dynamic_cast 中的类型必须是指向完整类类型或 void* 的指针或引用
	//double d = dynamic_cast<double>(ch);	//转换失败
}

class Father {
    
    };
class Son : public Father {
    
    };
class Other {
    
    };	//非关联类

//动态类型转换-支持上行转换,不支持下行转换
void func2() {
    
    
	/* 不允许向下转换-不安全 */
	//报错:运行时dynamic_cast的操作数必须包含多态类类型
	Father* father = NULL;
	//Son* son = dynamic_cast<Son*>(father);	//转换失败

	/* 允许向上转换-安全 */
	Son* son = NULL;
	Father* f = dynamic_cast<Father*>(son);		//转换成功

	//无效转换:非关系类之间不可进行动态类型转换
	//报错:运行时dynamic_cast的操作数必须包含多态类类型
	//Other* other = dynamic_cast<Other*>(father);//转换失败
}


class Animal {
    
    
	virtual void test() {
    
    }
};

class Dog : public Animal {
    
    
	//重写父类虚函数
	virtual void test() {
    
    }
};

//动态类型转换-支持多态调用
void func3() {
    
    
	//发生多态时,编译器认为类型转换总是安全的
	Animal* animal = new Dog;
	
	//支持多态调用时的下行转换
	Dog* dog = dynamic_cast<Dog*>(animal);
}

3 常量类型转换(const_cast)

语法
添加const修饰const 指针/引用类型 变量 = const_cast<const 指针/引用类型>(原变量);
去除const修饰指针/引用类型 变量 = const_cast<指针/引用类型>(const修饰的变量);

作用:仅适用于修改指针或引用类型的const属性,如常量指针/引用非常量指针/引用的转换。
(1)常量指针被转化为非常量指针,且仍指向原对象;
(2)常量引用被转化为非常量引用,且仍指向原对象;

注1:不能对非指针非引用的变量使用const_cast操作符,用于移除const属性。否则编译器报错:const_cast中的类型必须是指针、引用或指向对象类型成员的指针
注2:int类型的变量存储在栈区const int类型的变量存储在符号表

示例:指针或引用的常量类型转换

#include <iostream>
using namespace std;

//常量指针与非常量指针的转换
void func1() {
    
    
	//常量指针→非常量指针
	const int* cp = NULL;
	int* p = const_cast<int*>(cp);

	//非常量指针→常量指针
	char* q = NULL;
	const char* cq = const_cast<const char*>(q);
}

//常量引用与非常量引用的转换
void func2() {
    
    
	//常量引用 → 非常量引用
	const int& ca = 1;
	int& a = const_cast<int&>(ca);

	//非常量引用 → 常量引用
	char ch = 'x';
	char &b = ch;
	const char& cb = const_cast<const char&>(b);
}

//const_cast不能用于非指针和非引用的转换
void func3() {
    
    
	int a = 10;
	//报错:const_cast 中的类型必须是指针、引用或指向对象类型成员的指针
	//const int ca = const_cast<const int>(a);	//转换失败
}

4 重新解释转换(reinterpret_cast)

重新解释转换reinterpret_cast最灵活最不安全的类型转换机制,容易产生安全问题,不建议使用
作用:将一种数据类型转换为另一种数据类型,如整型转换为指针类型、自定义数据类型指针转换为非关联类指针。

示例

#include <iostream>
using namespace std;

void func1() {
    
    
	//整数 → 指针
	int a = 10;
	int* p = reinterpret_cast<int*>(a);
}

class Father {
    
    };
class Son : public Father {
    
    };
class Other {
    
    };		//非关联类

void func2() {
    
    
	//整型 → 非关联类指针
	int a = 10;
	Other* p1 = reinterpret_cast<Other*>(a);

	//自定义数据类型指针 → 非关联类指针
	Father *father = NULL;
	Other* p2 = reinterpret_cast<Other*>(father);
}

5 类型转换总结

转换机制 作用 安全性
静态类型转换static_cast ①内置基本数据类型的转换
②父子类指针或引用的转换:向上转换、向下转换
较不安全:向下转换
动态类型转换dynamic_cast 父子类指针或引用的转换:多态调用、向上转换 安全
常量类型转换const_cast 仅适用于修改指针或引用类型的const属性:常量类型非常量类型转换 /
重新解释转换reinterpret_cast 将一种数据类型转换为另一种数据类型,最灵活最不安全 不安全

猜你喜欢

转载自blog.csdn.net/newson92/article/details/113875275