C++ 的强制类型转换
目录(转换方式):
1 、static_cast
2 、dynamic_cast
3、reinterpret_cast
4、const_cast
5、类型转换使用建议
一、 static_cast: 用于基本类型之间的转换
static_cast<>() 可以说是神通广大。
使用方法 : type y = static_cast< type >( expression );
// type-> 需要转换成的目标类型
// expression -> 需要转换的变量或者表达式
//1、基本类型的转化
int age = 100;
double age1=static_cast< double >( age ); //将 int类型转换成 double
//2、父子类之间的转换 class Dog 继承至 class animal
Dog *dog1=new Dog();
Animal *al=static_cast<Animal *>(dog1); //之类性转换成父类型
Dog *dog1=static_cast<Dog *>(al); //父类型的指针到子类的指针(父类到子类有风险)
Dog dog2;
Animal &a2=static_cast<Animal &>(dog2); //之类性转换成父类型
Dog &dog2=static_cast<Dog &>(a2); //父类型的引用到子类的引用(父类到子类有风险)
// 3、把空指针转换成目标类型的空指针
int *p=static_cast<int *>(NULL);
Dog *dog=static_cast<Dog*>(NULL);
// 4、把任何类型的表达式转换成void类型
int *p=new int[19];
void *vp=static_cast<void *>(p);
vp=p;
常见的基本数据类型:
-
整数类型(int):用于表示整数,包括正整数、负整数和零。
-
浮点数类型(float和double):用于表示实数,即带有小数点的数。
-
字符类型(char):用于表示单个字符,可以是字母、数字、符号等。
-
布尔类型(bool):用于表示真或假、是或否等。
使用时的陷阱:
1、static_cast : 可以用于类的上下转型。但是,这种转换方式没有运行时检查,因此可能会导致安全问题。
2、static_cast
不能转换掉表达式的const、volatile或unaligned属性。如果需要改变这些属性,需要考虑其他类型的转换或使用方法。
二、 dynamic_cast 用于类之间的上下转型
dynamic_cast
主要用于实现多态性,通过基类的指针或引用来调用派生类的成员函数。
dynamic_cast ->如果类型转换失败 返回 NULL
说明: nullptr
和 NULL
在C++中都用于表示空指针,那么两者有何区别
- nullptr 是C++11新引入的 ,
nullptr
的含义更加明确,它专门用于表示空指针,没有其他的含义,更安全。 NULL
在C++中通常被定义为整型常量,需要隐式地转换为指针类型。
使用方式: type y = dynamic_cast< 目标类型 >( 源指针 )*
#include<iostream>
#include<string>
using namespace std;
class Test {
public:
//构造函数
Test(int age = 12, string name = " 吴献丰 ") {
age_ = age;
name_ = name;
}
virtual void paly() {
cout << "一起去玩吗?" << endl;
}
//析构函数
~Test() { }
protected:
int age_;
string name_;
};
class Test2 : public Test {
public:
Test2(string name) {
name_ = name;
}
void paly() {
cout << "一起去吃汉堡王吗?" << endl;
}
Test2() { }
private:
string addr_;
};
int main() {
Test2 *test2 = new Test2( "重庆秀山" );
// dynamic_cast ->如果类型转换失败 返回 NULL
Test *test = dynamic_cast< Test * > ( test2 );
if (test == NULL) {
cout << "类型转换失败: " << endl;
}else {
test->paly(); //这里调用的是 派生类的 paly方法->输出一起去吃汉堡王吗?
}
return 0;
}
无效的转换 : 基类 -》 派生类
// Test2 继承至 Test
Test* test = new Test();
Test2 *test2 = new Test2();
Test2 *t = dynamic_cast< Test2 * > ( test );
Test2* t = dynamic_cast<Test2*>(test);
if (t == NULL) {
cout << "类型转换失败" << endl; //程序运行后会输出这句话
}
为什么要使用 dynamic_cast :
1、可以使用基类指针来操作不同类型的对象,而无需知道对象的具体类型。
2、实现基类和派生类的安全转换。如果转换成功,我们可以通过基类的指针来访问派生类的方法。
三、reinterpret_cast 常用于不同类型指针之间的强制转换,甚至是将指针转 换成 整数.
使用方式: type y = reinterpret_cast< type >( expression )
// type-> 需要转换成的目标类型
// expression -> 需要转换的变量或者表达式
Demo : 常见的几种用法
1 、指针之间的转换:例如将int指针转换为char指针。
int x = 10;
int* int_ptr = &x;
char* char_ptr = reinterpret_cast<char*>(int_ptr);
2、指针与整数之间的转换:可以指针转换为整数类型,或将整数类型转换为指针。
int x = 10;
int* int_ptr = &x;
int int_val = reinterpret_cast<int>(int_ptr);
注意:
- 这种转换方式没有进行类型检查,因此风险较高。
四、const_cast 主要用于去除对象的常量性限制,或者添加常量性限制
将const对象转换成非const对象 进行修改。
使用方式:
type y = const_cast< type >( expression )
举例说明:
int a = 3;
const int *b = &a; // b是一个指向常量的指针,不能通过b修改a的值
int* c = const_cast<int*>(b); // 使用const_cast去除b的const属性,得到指向非常量的指针c
*c = 4; // 通过c修改a的值
cout << a << *c; // 输出两个4,表明a的值已经被修改
补充: 对于 const的位置,起到的作用
-
const 加在最前面 : const int *age = &a; //
age
所指向的地址的内容不能被改变。 -
const 加在后面: int * const age=&a; //
age
的值(也就是它所指向的地址)在初始化后不能再被改变。也就是说age只能指向a。 -
const 加在前后 : const int * const age = &a; //
age
所指向的地址的内容不能被改变 , 同时 age 只能指向a, 指向其他变量的地址会报错。也就是说age
的值和它所指向的地址的内容都不能被改变。
注意:
1、const_cast
不能用于修改变量本身的const属性,只能修改指针或引用的const属性,再通过间接修改的方式来改变变量的值
2、常量字符串不能去 const 修改。编译通过了,但是程序运行时之间崩了。
3、在去常量限定符之间,要保证指针所指向的内存能够修改,不能修改会引起异常。
4、仅针对指针和引用。
类型转换使用总结:
1、static_cast 静态·类型·转换,编译时C++编译器会对类型进行检查,所以能隐射类型转换的,就用static_cast.
2、dynamic_cast<>() 动态类型转换,安全的虚基类和子类之间转换,运行时也会进行类型检查。
3、const_cast<>() 去除变量的只读属性。
4、不同类型之间进行强制类型转换,用reinterpret_cas<>()进行重新解释。
5、static_cast <>()和reinterpret_cas<>(),基本上把c语言中的 强制类型转换给覆盖了。值得注意的是reinterpret_cas<>()很难保证移植性。
C++大牛建议: 一般情况下,不建议进行类型转换,避免进行类型转换。