旧式转型 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
静态类型转换(斯文的劝导,温柔的转换),类似于 C 语言中的隐式转换,如 int 转换成 char 。
主要用法:
用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。上行指针或引用(派生类到基类)转换安全,下行(基类到派生类)转换不安全。
用于基本数据类型之间的转换,如把 int 转换成 char ,把 int 转换成 enum 。这种转换的安全性也要开发人员来保证。
把空指针转换成目标类型的空指针。
把任何类型的表达式转换成 void 类型。
#include
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);
int* pi = new int[10];
void* vp = static_cast<void*>(pi);
重新解释类型(挂羊头,卖狗肉))不同类型间的互转,数值与指针间的互转。
用法: TYPE b = reinterpret_cast ( a )
TYPE 必须是一个指针、引用、算术类型、函数指针
忠告: 滥用 reinterpret_cast 运算符可能很容易带来风险。 除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。
#include
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(a1); //输出喵喵喵
//Cat* cat2_p = static_cast(dog1_p); //报错,不同类型指针转换不能使用static_cast
Cat* cat2_p = reinterpret_cast<Cat*>(dog1_p); //但是这个强制转换不会报错
cat2_p->cry(); //喵喵喵
Animal& a2 = dog1;
Dog& dog3 = reinterpret_cast<Dog&>(a2);//引用强转用法
动态类型转换
将一个基类对象指针 cast 到继承类指针,dynamic_cast 会根据基类指针是否真正指向继承类指针来做相应处理。失败返回 null ,成功返回正常 cast 后的对象指针。
将一个基类对象引用 cast 继承类对象,dynamic_cast 会根据基类对象是否真正属于继承类来做相应处理。失败抛出异常 bad_cast 。
注意: dynamic_cast 在将父类 cast 到子类时,父类必须要有虚函数一起玩。
#include
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;
}
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;
}
去掉 const 属性。(仅针对于指针和引用)
#include
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(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 ++大牛建议: 一般情况下,不建议进行类型转换,避免进行类型转换。