1、介绍
C++中的强制类型转换是一种将一个数据类型转换为另一个数据类型的操作。在C++中,有四种类型的强制类型转换:静态转换、动态转换、常量转换和重新解释转换。
(1)静态转换(static_cast):静态转换是最常用的一种类型转换,它可以在不同但相关的类型之间进行转换,如基本数据类型之间的转换、父类指针向子类指针的转换等。但是需要注意的是,静态转换没有运行时类型检查,因此在进行转换时需要确保类型之间是相关的,否则可能会导致错误。
(2)动态转换(dynamic_cast):动态转换主要用于类层次结构中的指针或引用类型之间的转换。它在运行时进行类型检查,只有当类型之间存在继承关系时才能进行转换。如果转换失败,即目标类型不是源类型的派生类或基类,则返回空指针(对于指针类型)或抛出std::bad_cast异常(对于引用类型)。
(3)常量转换(const_cast):常量转换主要用于去除指针或引用类型的常量属性。它可以将const修饰的对象转换为非const修饰的对象,从而可以修改原本被限制为只读的对象。
(4)重新解释转换(reinterpret_cast):重新解释转换是一种较为底层的转换方式,它可以将一个指针或引用类型转换为另一个不相关的指针或引用类型。这种转换方式非常危险,因为它不会进行任何类型检查,可能会导致未定义的行为。
2、static_cast
用法:
static_cast<new_type> ( expression )
该运算符把expression转换为new_type类型。
#include <iostream>
using namespace std;
class Base {
public:
int a;
void fun1() { cout << "Base::fun1" << endl; }
void fun2() { cout << "Base::fun2" << endl; }
};
class Derive : public Base {
public:
int b;
void fun2() { cout << "Derive::fun2" << endl; }
void fun4() { cout << "Derive::fun4" << endl; }
};
int main()
{
// C语言的强制类型转换
int aa = 10;
int ab = 3;
double result_1 = (double)aa / (double)ab;
// C++的强制类型转换
int ac = 10;
int ad = 3;
double result_2 = static_cast<double>(ac) / static_cast<double>(ad);
cout << "result_1: " << result_1 << ", result_2: " << result_2 << endl;
char ae = 'a';
short af = 10;
int ah = static_cast<int>(ae);
int ai = static_cast<short>(af);
cout << "ah: " << ah << ", ai: " << ai << endl;
int aj = 20;
const int ak = static_cast<const int>(aj);
cout << "ak: " << ak << endl;
Base al;
Derive am;
Base* an = static_cast<Base*>(&am); //派生类指针->父类指针
Derive* au = static_cast<Derive*>(&al); //父类指针->派生类指针
an->fun1(); // 调用父类的fun1
an->fun2(); // 调用父类的fun2
//an->fun4(); // 编译错误:error: no member named 'fun4' in 'Base'。 因为fun4是派生类的成员函数,只能通过派生类对象进行访问。
au->fun1(); // 调用父类的fun1
au->fun2(); // 调用派生类类的fun2
au->fun4(); // 调用派生类类的fun4,fun4是派生类的成员函数,而不是父类的成员函数
return 0;
}
结果:
result_1: 3.33333, result_2: 3.33333
ah: 97, ai: 10
ak: 20
Base::fun1
Base::fun2
Base::fun1
Derive::fun2
Derive::fun4
3、const_cast
用法:
const_cast<new_type> ( expression )
该运算符仅用于进行去除const属性的转换,它也是四个强制类型转换运算符中唯一能够去除 const属性的运算符。将const引用转换为同类型的非const引用,将const指针转换为同类型的非const指针。
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
//移除const限定
const int ia = 10;
int* ib = const_cast<int*>(&ia);
cout << "ib: " << *ib << endl;
//添加const限定
int ic = 42;
const int* id = const_cast<const int*>(&ic);
cout << "id: " << *id << endl;
return 0;
}
结果:
ib: 10
id: 42
4、reinterpret_cast
用法:
reinterpret_cast<new_type> ( expression )
用于将一个指针类型转换为其它的指针类型,但它不改变其操作数的比特表示,只进行了最外层的转换,没有进行二进制的解释。这种转换的结果会导致实际编程中的指针指向的内容是不明确的,因此需要开发者自行确保转换的安全性。应谨慎使用。
举例:
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
int ra = 10;
int* rb = &ra;
// 将 int* 转换为 double*
double* rc = reinterpret_cast<double*>(rb);
cout << "rc: " << *rc << endl;
// 将 int* 转换为 char*
char* rd = reinterpret_cast<char*>(rb);
cout << "rd: " << *rd << endl;
return 0;
}
结果:
rc: -9.25596e+61
rd:
5、dynamic_cast
用法:
dynamic_cast<new_type> ( expression )
dynamic_cast专门用于将多态基类的指针或引用强制转换为派生类的指针或引用,而且能够检查转换的安全性。对于不安全的指针转换,转换结果返回 NULL 指针。
dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。
dynamic_cast与static_cast是相对的,dynamic_cast是“动态转换”的意思,static_cast是“静态转换”的意思。
dynamic_cast会在程序运行期间借助RTTI进行类型转换,这就要求基类必须包含虚函数。
static_cast在编译期间完成类型转换,能够更加及时地发现错误。
举例:
#include <iostream>
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
void DerivedMethod() {
std::cout << "Derived method called." << std::endl;
}
};
int main() {
Base* da = new Derived;
Derived* db = dynamic_cast<Derived*>(da);
if (db) {
db->DerivedMethod();
}
else {
std::cout << "dynamic_cast failed." << std::endl;
}
delete da;
return 0;
}
结果:
Derived method called.