C++四种类型转换操作符 static_cast、dynamic_cast、reinterpret_cast、const_cast介绍

前言

  • C风格的强制类型转换很简单,都可以使用Type b = (Type)a形式转换。但这种方式存在一些缺点,比如信息丢失或精度损失,代码可读性的下降等。
  • 因此C++提供了四种类型转换符来应对不同场合。分别是static_castdynamic_castreinterpret_castconst_cast

四种类型比较

类型转换符用途特点
static_cast用于相关类型之间的转换
如基本数据类型之间的转换
派生类指针或引用转为基类指针或引用(上行转换)(总是安全的)
基类指针或引用转为派生类指针或引用(下行转换)(结果可能未定义)
编译时检查类型兼容性
适用于相关类型之间的转换
dynamic_cast主要用于基类和派生类之间的转换,会进行类型检查,
因此上行转换和上行转换都是安全的
运行时检查类型兼容性
适用于多态对象之间的转换
reinterpret_cast主要用于指针或引用类型之间的转换
指针与整型数据之间的转换
不进行类型检查,只是简单地重新解释数据的二进制表示
高风险,容易导致未定义行为
const_cast用于添加或移除变量的 const 或 volatile 属性用于添加或移除 const 或 volatile 属性
不影响其他类型属性

四种类型详细介绍

static_cast

  • 静态类型转换,类似C风格的强制转换。
  • 可以进行基本数据类型的转换,enumstructintcharfloatlong等。
    •   int data = 10010;
        char cData = static_cast<char>(data);
      
  • 不能转换指针类型,但是可以将指针与void*进行互转。
    •   	int data = 10010;
        	int *pData = &data;
        	long *plData = static_cast<long*>(pData);  // 不允许转换
      
    •   	int data = 10010;
        	int *pData = &data;
        
        	void *pvData = static_cast<void*>(pData);  // 可以转换
        	long *plData = static_cast<long*>(pvData); // 可以转换
      
  • 不能用于两个不相关类型的转换,比如将int*转为int
    •   	int data = 10010;
        	int *p1 = &data;
        
        	int num = static_cast<int>(p1);  //不允许转换
      
  • 从派生类指针或引用转换为基类指针或引用(上行转换)时,static_cast总是安全的。
    •   class Animal {
        public:
        	virtual void cry() {
        		std::cout << "Animal cry..." << std::endl;
        	}
        	virtual ~Animal() {}
        };
        
        class Dog :public Animal {
        public:
        	void cry() override {
        		std::cout << "Dog cry..." << std::endl;
        	}
        	void print() {
        		std::cout << "I am dog" << std::endl;
        	}
        };
        
        
        int main() {
        	Dog* pDog = new Dog;
        	// 子类转为父类是安全的
        	Animal* pAnimal = static_cast<Animal*>(pDog);
        	// 调用子类的cry方法
        	pAnimal->cry();
        	return 0;
        }
      
  • 从基类指针或引用转换为派生类指针或引用(下行转换)时,static_cast可以工作,但前提是必须确保基类指针实际上指向的是派生类对象。否则,结果将是未定义的。
    •   class Animal {
        public:
        	virtual void cry() {
        		std::cout << "Animal cry..." << std::endl;
        	}
        	virtual ~Animal() {}
        };
        
        class Dog :public Animal {
        public:
        	void cry() override {
        		std::cout << "Dog cry..." << std::endl;
        	}
        
        };
        
        class Cat :public Animal {
        public:
        	void cry() override {
        		std::cout << "Cat cry..." << std::endl;
        	}
        };
        
        
        int main() {
        	Animal* pAnimal = new Dog;
        
        	Dog* pDog = static_cast<Dog*>(pAnimal);
        	pDog->cry();   // 这里调用Dog的方法,是正常的
        
        
        	Cat* pCat = static_cast<Cat*>(pAnimal);
        	pCat->cry();   // 这里仍然调用Dog的方法,是不正确的
        
        	return 0;
        }
      

dynamic_cast

  • 动态类型转换。是一种运行时类型检查的强制类型转换操作符,主要用于处理基类与派生类之间的转换。
  • 如果是指针类型转换失败,会返回空,如果是引用类型转换失败,会抛出一个bad_cast异常。
  • 从派生类指针或引用转换为基类指针或引用(上行转换)。
    •   class Animal {
        public:
        	virtual void cry() {
        		std::cout << "Animal cry..." << std::endl;
        	}
        	virtual ~Animal() {}
        };
        
        class Dog :public Animal {
        public:
        	void cry() override {
        		std::cout << "Dog cry..." << std::endl;
        	}
        	void print() {
        		std::cout << "I am dog" << std::endl;
        	}
        };
        
        
        int main() {
        	Dog* pDog = new Dog;
        	// 子类转为父类
        	Animal* pAnimal = dynamic_cast<Animal*>(pDog);
        	// 调用子类的cry方法
        	pAnimal->cry();
        	return 0;
        }
      
  • 从基类指针或引用转换为派生类指针或引用(下行转换)。
    •   class Animal {
        public:
        	virtual void cry() {
        		std::cout << "Animal cry..." << std::endl;
        	}
        	virtual ~Animal() {}
        };
        
        class Dog :public Animal {
        public:
        	void cry() override {
        		std::cout << "Dog cry..." << std::endl;
        	}
        
        };
        
        class Cat :public Animal {
        public:
        	void cry() override {
        		std::cout << "Cat cry..." << std::endl;
        	}
        
        };
        
        
        int main() {
        	Animal* pAnimal = new Dog;
        
        	// 父类转为子类, 会进行类型检查
        	// 这里会转换成功
        	Dog* pDog = dynamic_cast<Dog*>(pAnimal);
        	if (pDog == NULL) {
        		std::cout << "pDog is null" << std::endl;
        		return -1;
        	}
        
        	pDog->cry();   
        
        
        	Cat* pCat = dynamic_cast<Cat*>(pAnimal);
        	// 这里会转换失败
        	if (pCat == NULL) {
        		std::cout << "pCat is null" << std::endl;
        		return -1;
        	}
        
        	pCat->cry();
        
        	return 0;
        }
      

const_cast

  • 主要用于去除const属性。直接看一个示例
    •   int main() {
        	int data = 10010;
        	const int* pcData = &data;
        
        	// 这样是无法修改的 
        	//*pcData = 10020;
        
        	// 可转为int*修改
        	int* pData = const_cast<int*>(pcData);
        	*pData = 10020;
        
        	// 打印结果都为10020
        	std::cout << "data: " << data << std::endl;
        	std::cout << "*pcData: " << *pcData << std::endl;
        	std::cout << "*pData: " << *pData << std::endl;
        
        	return 0;
        }
      

reinterpret_cast

  • 主要用于指针类型或者引用类型之间的转换。
  • 将一个指针类型转为另一个指针类型
    •   	int data = 10010;
        	int *pData = &data;
        	char *pCh = reinterpret_cast<char*>(pData);
      
  • 将一个引用类型转为另一个引用类型
    •   	int iData = 10010;
        	int &pData = iData;
        	char &cData = reinterpret_cast<char&>(pData);
      
  • 指针与整型数据之间的转换。
    •   	int iData = 10010;
        	char cData = 10;
        	long long lData = 678290;
        
        	// 结果可能未定义
        	char *pCh = reinterpret_cast<char*>(iData);
        	pCh = reinterpret_cast<char*>(cData);
        	pCh = reinterpret_cast<char*>(lData);
      
  • 不允许进行基本类型的转换
    •   	int iData = 10010;
        	// 不允许
        	char cData = reinterpret_cast<char>(iData);
      
  • 注意事项
    • 使用 reinterpret_cast进行不合适的转换可能会导致未定义行为。
    • reinterpret_cast的行为可能依赖于具体的硬件和编译器实现。因此,使用 reinterpret_cast编写的代码可能不具备良好的可移植性。
    • 尽量避免使用 reinterpret_cast,除非确实需要低级别的控制。大多数情况下,使用 static_castdynamic_cast更为安全和合适。
    • reinterpret_cast不提供任何类型的检查,因此使用时必须确保转换是合理的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大草原的小灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值