C++四种cast学习笔记
1.static_cast
static_cast
是一种更安全的转换方式,它在编译时检查转换的合法性。常见使用情形如下:
- (1) 非多态类型转换:可用于替换C中强制类型转换,与此同时,编译器隐式执行的任何类型转换,都可以使用
static_cast
显式完成,如整形和浮点型,void*
于具体类型指针之间转换或非const
类型转换为const
类型;
#include <iostream>
int main(int argc, char *argv[]) {
double x = 3.141592653589793;
int y = static_cast<int>(x);
float z = static_cast<float>(x);
std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl;
{
double *a = new double;
void *b = static_cast<void*>(a);
delete a;
}
return 0;
}
- (2) 向上转换:子类指针或引用转换为父类指针或引用,这种转换在类层次结构中是安全的;
- (3) 向下转换:父类指针或引用转换成子类指针或引用,这要求转换是合法的,即实际对象类型确实是目标子类类型,若不是,结果就是未定义的。
#include <iostream>
class Base {};
class Derived : public Base {};
int main(int argc, char *argv[]) {
Base *a = new Base();
Derived *b = new Derived();
// 向上转换,安全的转换
if (Base *x = static_cast<Base*>(b)) {
std::cout << "a is a Base" << std::endl;
}
// 向下转换,不安全的转换
if (Derived *y = static_cast<Derived*>(a)) {
std::cout << "b is a Derived" << std::endl;
}
delete a;
delete b;
a = nullptr;
b = nullptr;
return 0;
}
基类指针可以直接指向派生类对象,这个过程不需要显式转换。而能否合法转换,主要取决于二者间是否存在任一方向的隐式转换关系。
2.dynamic_cast
dynamic_cast
多用于类层次结构中父类和子类之间指针和引用的转换,由于运行时类型检查,因此可以保证下行转换的安全性。
#include <iostream>
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
virtual ~Derived() {}
};
int main(int argc, char *argv[]) {
Base *a = new Base();
Base *b = new Derived();
Derived *c = dynamic_cast<Derived*>(b);
Derived &d = static_cast<Derived&>(*b);
Derived &&e = static_cast<Derived&&>(*b);
delete a;
delete b;
a = nullptr;
b = nullptr;
return 0;
}
3.const_cast
const_cast
用于去除 const
或 volatile
限定符,只针对指针(包括 this
指针)和引用,大部分使用是将常量指针转换成常指针(常量指针指向空间内容不允许被修改,但使用 const_cast
强制转换就可以修改)。
#include <iostream>
#include <string>
void Print(char *str) {
std::cout << str << std::endl;
}
class A {
public:
A() = default;
~A() = default;
void Change(int value) const {
// const_cast 用于移除const属性限定符
const_cast<A*>(this)->value_ = value;
std::cout << "value changed to " << value_ << std::endl;
}
private:
int value_;
};
int main(int argc, char *argv[]) {
// 1.指针操作
std::string str = "Hello, World!";
// str.c_str()返回数据类型为const char *
// 使用const_cast将const char *转换为char *
Print(const_cast<char*>(str.c_str()));
// const_cast不能修改基本类型
// int *data = const_cast<int*>(str.c_str()); // 错误
// 2.引用操作
int a = 10;
const int &b = a;
int &c = const_cast<int&>(b);
c = 20;
std::cout << "a = " << a << std::endl;
// 3.this指针
A a{};
a.Change(10);
return 0;
}
需要注意的是,const_cast
只能转换类型限定符,不能修改基本类型。
4.reinterpret_cast
从字面意思来看为重新诠释转型,相当于C语言的强制转换,可用于任意指针(或引用)间转换,但不检查安全性,它只告诉编译器把指针从一种类型重新解释成另外一种类型。
#include <iostream>
int main(int argc, char *argv[]) {
int i = 7;
reinterpret_cast<unsigned int &>(i) = 42;
std::cout << "i = " << i << std::endl;
void *p = &i;
int *ip = reinterpret_cast<int *>(p);
*ip = 13;
std::cout << "i = " << i << std::endl;
return 0;
}
5.参考资料
- [1] C++ 四种cast 详解