- Published on
都2023年了,还在用C风格的强转吗?
都2023年了,还在用C风格的强转吗?
C风格
int a = 1;
float b = (float)a; // 普通的强转
float c = float(a); // 函数风格的强转
上面的例子为C风格的强制类型转换----简单粗暴!直接使用"()"括起来即可。 没有类型检查,直接硬转,转的对错全凭程序员的“造化”了。
在C++中,强制类型转换分为四种,当然在C++中仍然支持C风格的强转,但是C++保留C风格的强转仅仅是为了语言兼容性的考虑。 因此,都2023年了,还在用C风格的强转吗?
C++中的四种强制类型转换分别用于不同的目的,这四种强制类型转换,每一种都对应着一个名字, C++中这么分是为了提供更丰富的含义和功能以及更好的类型检查机制,方便代码的书写与维护。 因此,都2023年了,还在用C风格的强转吗?
下面我们来认识一下这四种强制类型转换,有时也称它们为强制类型转换运算符或者强制类型转换操作符。
static_cast
称为静态转换,可以理解为正常转换,在编译期间就会进行类型转换的检查, 通常用于相关类型之间的互相转换,主要用于数值类型之间的相互转换。
enum class Week {
Mondy = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
};
int a = 1;
float b = static_cast<float>(a);
Week day = static_cast<Week>(a);
reinterpret_cast
称为重新解释转换,也会在编译期间进行类型转换的检查,但是这是一个非常自由且奇怪的类型转换, 使用此转换会将数据以二进制存在的形式进行重新解释。通常用于无关类型的互相转换,也就等于乱转、瞎转、自由转、爱咋转咋转。 使用最多的情况为与void*进行相互转换。
class Bag {
public:
Bag() = default;
~Bag() = default;
void Set(int thing) {
thing_ = thing;
}
int Get() {
return thing_;
}
private:
int thing_ = 0;
};
void Transfer(void *trans) {
Bag *bag = reinterpret_cast<Bag*>(trans);
bag->Set(9);
}
int main() {
Bag *bag = new Bag();
Transfer(reinterpret_cast<void*>(bag));
std::cout << bag->Get() << std::endl;
delete bag;
return 0;
}
dynamic_cast
称为动态转换,此强制类型转换不会在编译期间进行类型检查,而是在运行时进行类型的识别与检查,通常用于父类型向子类型转换。 dynamic_cast能将父类的指针或者引用安全的转换为子类的指针或者引用,其实是在帮助开发者做安全检查, 不过使用dynamic_cast有个一前提条件,那就是父类中必需至少又一个虚函数! dynamic_cast会在运行时做类型检查,因此类型检查是要付出代价的,不过与安全性相比,这个代价是非常值得的。
class Base {
public:
Base() = default;
virtual ~Base() = default;
virtual void Play() = 0;
};
class Player : public Base {
public:
Player() = default;
~Player() = default;
void Play() override {
std::cout << "play" << std::endl;
}
};
class Test {
public:
Test() = default;
~Test() = default;
void Play() {
std::cout << "test play" << std::endl;
}
};
int main() {
Base *base = new Player();
Player *player = dynamic_cast<Player*>(base);
if (player != nullptr) {
player->Play();
}
Test *test = dynamic_cast<Test*>(base);
if (test != nullptr) { // test is not subclass of Base, so test must is nullptr.
test->Play();
}
delete base;
return 0;
}
const_cast
称为常量转换,const_cast会在编译期间进行类型转换的检查,这个类型转换只能做一件事,不过也就只有const_cast能够做这件事, 那就是将常量指针或者引用转换成非常量指针或者引用,需要注意的是,const_cast只能转换指针或者引用类型,不能转换普通数值类型。 当你的代码里出现了const_cast,那说明你要重新设计一下你的代码了。
class Test {
public:
Test() = default;
~Test() = default;
int value = 0;
};
void Change(const Test &test) {
Test &change = const_cast<Test&>(test);
change.value = 1;
}
int main() {
Test test;
std::cout << test.value << std::endl;
Change(test);
std::cout << test.value << std::endl;
return 0;
}