C语言转换
cpp
#include <iostream>
int main() {
int x = 256;
char c1 = x;//隐式转换
char x2 = (char)x;//显示转换
}
优点是简洁,代码书写方便,适合快速原型开发。缺点是安全性差:隐式转换可能造成数据截断或精度丢失,且不易被察觉;显式转换虽然意图明确,但同样缺乏类型检查,容易埋下隐患。因此在实际工程中,应尽量避免使用 C 风格转换,转而使用 C++ 提供的类型转换运算符。# C++的4种方式
C++ 风格转换语法冗长,书写繁琐,有意"恶心"程序员,目的是让转换操作在代码中显得突兀、醒目。这样一旦程序出现缺陷,开发者能第一时间联想到可能是类型转换出了问题,从而快速定位。优点是安全性高:每种转换运算符都有明确的适用场景和检查机制,编译器能在编译期或运行期发现错误,避免静默的数据损坏。## 静态转换(static_cast)
static_cast 是最基础、最常用的转换运算符,用于编译期可确定的类型安全转换,全程无运行时类型检查,因此没有任何运行时性能开销,仅在编译期完成类型转换处理。它适用于:基础类型之间的转换(如 int 转 char、float 转 int)、任意指针与 void* 之间的互转、上行转换(派生类转基类)等。需要注意的是,static_cast 不执行运行时安全检查,若用于下行转换(基类转派生类),程序员必须自行保证对象实际类型正确,否则会产生未定义行为。
cpp
#include <iostream>
class CStr : public std::string {
};
int main() {
// 1. 基础类型的转换
int num = 65;
char ch = static_cast<char>(num);
//任意指针与void*之间的转换
int value = 42;
int* intPtr = &value;
void* voidPtr = static_cast<void*>(intPtr);
//上行转换(Upcasting),派生类转成基类
CStr str;
std::string* pStr = &str;
//下线转换:基类转成父类,有可能出错
std::string str2;
CStr* pStr2 = static_cast<CStr*>(&str2);
}
动态转换dynamic_cast
dynamic_cast 是运行时类型识别(RTTI)的核心工具,用于在继承层次中进行安全的向下转换和交叉转换。使用它必须满足以下条件:
- 基类必须包含至少一个虚函数,否则无法使用 dynamic_cast,编译器会报错(因为 RTTI 依赖虚表)。
- 禁止在构造函数和析构函数中使用 dynamic_cast,此时对象的虚表还未完全构建或已开始销毁,转换结果不可预期。
- 频繁使用 dynamic_cast 会影响程序性能,因为它需要运行时遍历继承链进行类型比对;在核心高频场景,可通过虚函数多态或其他设计模式(如访问者模式)替代下行转换,避免性能损耗。
转换失败的处理方式:指针转换失败返回 nullptr,引用转换失败抛出 std::bad_cast 异常。因此使用引用转换时,必须用 try-catch 包裹,否则程序会直接崩溃。## 基类必须有虚函数
cpp
#include <iostream>
class CStr : public std::string {
};
int main() {
std::string str2;
CStr* pStr2 = dynamic_cast<CStr*>(&str2);
}
编译上述代码,VS2019 会报出如下错误:
严重性 代码 说明 项目 文件 行 禁止显示状态
错误(活动) E0698 运行时 dynamic_cast 的操作数必须包含多态类类型
这是因为 std::string 没有虚函数,不是多态类型,编译器无法为其生成 RTTI 信息,因此 dynamic_cast 无法工作。解决办法是:确保基类至少含有一个虚函数(如虚析构函数),或者改用 static_cast 并自行保证类型安全。
指针转换失败
指针转换失败会,返回nullptr。如以下代码:
cpp
#include <iostream>
class A {
virtual int Age() { return 0; };
};
class B :A {
};
int main() {
A a;
B* b= dynamic_cast<B*>(&a);
}
引用转换失败
引用转换失败会崩溃。如以下代码:
cpp
int main() {
A a;
B& b= dynamic_cast<B&>(a);
}
const_cast
取消掉常属性。
cpp
#include <iostream>
void Out(int& x) {
std::cout << x << std::endl;
}
int main() {
const int a=3;
Out(const_cast<int&>(a));
}
只是让编译能通过,仍然是常量。
重新解释转换(reinterpret_cast)
不做任何编译时,运行时检测。由程序员保证正确性。非底层库勿用。
cpp
#include <iostream>
int main() {
int a;
std::string str;
//无关类型转换
int* p = reinterpret_cast<int*>(&str);
//执行和整数互转
int adr = reinterpret_cast<int>(&str);
std::string* pStr = reinterpret_cast<std::string*>(adr);
}
扩展阅读
| 计算几何为骨,排样优化为魂 |
|---|
| 作品一:亲士套料工具箱 作品二: 亲士CAD工具箱 |
| 经典文章推荐:二维排样 |
| 万物皆数学 |
| 查阅鄙人的博文,请点击博文下载学院导航 |
| 活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。
