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