网站外包,东莞住建局官网查询,专业网站seo优化公司,ai特效字体网站C/C类型转换
1. C类型转换
C 语言中的类型转换主要分为两种#xff1a;隐式类型转换 (Implicit Conversion) - 由编译器自动完成。显式类型转换 (Explicit Conversion) - 由程序员强制指定#xff0c;也称为强制类型转换。1.2 隐式类型转换
编译器在编译时自动进行的转换类型转换
1. C类型转换
C 语言中的类型转换主要分为两种隐式类型转换 (Implicit Conversion) - 由编译器自动完成。显式类型转换 (Explicit Conversion) - 由程序员强制指定也称为强制类型转换。1.2 隐式类型转换
编译器在编译时自动进行的转换通常发生在不同数据类型的变量混合运算、赋值或函数调用时。
转换规则通常遵循向上转换原则
int - unsigned int - long - unsigned long - long long - unsigned long long - float - double - long double常见发生的场景
int i 10;
float f 3.14;
double d i f; // i 被自动转换为 float 参与运算结果再转换为 double 赋值给 d1.3 强制类型转换
当用户需要明确地将一种数据类型转换为另一种时使用。它使用强制类型转换运算符语法是在要转换的目标类型前加上括号然后放在值或表达式前面。
常见发生的场景
int a 5, b 2;
float result;
result a / b; // 错误结果是 2.0 (整数除法)
result (float)a / b; // 正确结果是 2.5。将 a 转为 floatb 也会被隐式转换为 float将 void 指针转换为具体类型指针
void* generic_ptr;
int* int_ptr;
int x 10;generic_ptr x; // 合法任何指针都可以赋值给 void*
// *generic_ptr; // 错误不能对 void* 解引用
int_ptr (int*)generic_ptr; // 必须强制转换回 int*
printf(%d\n, *int_ptr); // 输出 10注意 在 C 语言中从 void* 转换到其他指针类型必须使用强制转换而在 C 中 static_cast 可以完成这个工作并且从 void* 到其他指针类型的隐式转换在 C 中是非法的。2. C中的类型转换
2.1 隐式类型转换C支持内置类型向自定义类型之间的转换内置类型转换为自定义类型需要构造函数的支持。C支持自定义类型转换为内置类型通过运算符重载 operator type () 的函数支持。C支持自定义类型向自定义类型之间的转换需要对应类型的构造函数支持。2.1.1 内置类型 - 自定义类型通过构造函数
#include iostreamclass Meter {
private:double value;
public:// 关键接收单一参数的构造函数// 定义了从 double - Meter 的转换规则Meter(double val) : value(val) {std::cout 构造函数被调用将 double val 转换为 Meter std::endl;}
};int main() {Meter m1 5.7; // 隐式转换double - Meterreturn 0;
}注意 使用 explicit 关键字可以禁止隐式转换只允许显式转换。2.1.2 自定义类型 - 内置类型通过转换函数
通过在类中定义 operator type() 成员函数可以实现从自定义类型到内置类型的转换。
#include iostreamclass Meter {
private:double value;
public:Meter(double val) : value(val) {}// 转换函数Meter - doubleoperator double() const {std::cout 转换函数被调用将 Meter 转换为 double: value std::endl;return value;}
};int main() {Meter m(5.7);// 自定义类型 - 内置类型double length_in_double m; // 隐式调用 operator double()std::cout 转换为 double 的值: length_in_double std::endl;return 0;
}通过operator bool()函数可以将自定义类型当作判断条件。2.1.3 自定义类型 - 自定义类型通过构造函数或转换函数
#include iostreamclass Kilometer; // 前向声明class Meter {
private:double value;
public:Meter(double val) : value(val) {}double getValue() const { return value; }// 也可以定义到 Kilometer 的转换函数// operator Kilometer() const;
};class Kilometer {
private:double value;
public:Kilometer(double val) : value(val) {}// 关键定义接收 Meter 参数的构造函数// 提供了 Meter - Kilometer 的转换路径Kilometer(const Meter m) : value(m.getValue() / 1000.0) {std::cout Kilometer 构造函数将 Meter 转换为 Kilometer std::endl;}void display() const {std::cout value kilometers std::endl;}
};// Meter 中转换函数的实现
// Meter::operator Kilometer() const {
// return Kilometer(value / 1000.0);
// }int main() {Meter m(1500.0); // 自定义类型 - 自定义类型Kilometer km m; // 隐式转换Meter - Kilometerkm.display(); // 输出: 1.5 kilometersreturn 0;
}对于转换函数也可以使用 explicit 关键字来禁止隐式转换
explicit operator double() const {return value;
}Meter m(5.7);
double d1 m; // 错误不能隐式转换
double d2 static_castdouble(m); // 正确显式转换2.2 显示类型转换
2.2.1 static_cast
静态转换最常用的显式转换用于在编译期进行有明确关联的安全转换。
场景基本数据类型之间的转换void 指针与具体类型指针之间的转换类层次结构中的上行转换派生类→基类int i 10;
double d static_castdouble(i); // int - doublevoid* voidPtr i;
int* intPtr static_castint*(voidPtr); // void* - int*2.2.2 reinterpret_cast
reinterpret_cast 用于在两种不相关类型之间进行转换其本质是对原始数据的底层位模式进行重新解释也就是说转换后对原有内存的访问解释已经完全改变了。
场景任意指针类型之间的转换指针和整数之间的转换int i 0x12345678;
char* p1 reinterpret_castchar*(a);2.2.3 const_cast
const_cast⽤于const类型到⾮const类型的转换去掉了const属性。
void oldFunction(char* str) {cout str endl;
}const char* message Hello;// oldFunction(message); // 错误不能将 const char* 转换为 char*
oldFunction(const_castchar*(message)); // 正确// 危险示例
const int ci 10;
int* badPtr const_castint*(ci);
*badPtr 20; // 未定义行为2.2.4 dynamic_castdynamic_cast⽤于将基类的指针或者引⽤安全的转换成派⽣类的指针或者引⽤。如果基类的指针或者引⽤时指向派⽣类对象的则转换回派⽣类指针或者引⽤时可以成功的如果基类的指针指向基类对象则转换失败返回nullptr如果基类引⽤指向基类对象则转换失败抛出bad_cast异常。其次dynamic_cast要求基类必须是多态类型也就是基类中必须有虚函数。因为dynamic_cast是运⾏时通过虚表中存储的type_info判断基类指针指向的是基类对象还是派⽣类对象。场景
安全的下行转换基类→派生类
要求
基类必须有虚函数多态类型
class Base { virtual void foo() {} };
class Derived : public Base {};Base* basePtr1 new Derived(); // 实际指向 Derived
Base* basePtr2 new Base(); // 实际指向 Base// 安全的下行转换
Derived* d1 dynamic_castDerived*(basePtr1); // 成功
Derived* d2 dynamic_castDerived*(basePtr2); // 失败返回 nullptrif (d2) {// 安全操作
} else {cout 转换失败 endl;
}// 引用转换失败会抛出异常
try {Derived rd dynamic_castDerived(*basePtr2);
} catch (const std::bad_cast e) {cout 引用转换失败 endl;
}dynamic_cast 的实现基础是 RTTI运行时类型信息。编译器会为每个包含虚函数的类生成额外的类型信息这些信息在程序运行时可用。什么是RTTIRTTI 是 C 提供的一种机制允许程序在运行时获取和操作对象的类型信息。它让程序能够动态地确定对象的实际类型即使是通过基类指针或引用来操作对象。typeid运算符用于获取对象的类型信息返回一个 std::type_info 对象的引用。dynamic_cast用于在继承层次中进行安全的类型转换依赖于 RTTI 信息。注意C/C都不是类型安全的语言。