找人做公司网站,logo设计公司排名,wordpress后台没有菜单,最缺工的一百个职业目录
C语言中的类型转换
C中的类型转换
C中的类型转换操作符
static_cast
reinterpret_cast
const_cast
volatile关键字
赋值兼容
dynamic_cast C语言中的类型转换
基本概念#xff1a;赋值运算符左右两侧类型不同#xff0c;或形参与实参类型不匹配…目录
C语言中的类型转换
C中的类型转换
C中的类型转换操作符
static_cast
reinterpret_cast
const_cast
volatile关键字
赋值兼容
dynamic_cast C语言中的类型转换
基本概念赋值运算符左右两侧类型不同或形参与实参类型不匹配或者返回值类型与接收返回值类型不一致时需要发生类项转换C语言中有两种形式的类型转换隐式类型转换和显示类型转换
注意事项有关联的类型才可以相互转换小类型会转换为大类型
整型之间的隐转int、long、short整型和浮点数间的隐转整型和字符型间的隐转bool和整型、指针间的隐转整数0和空指针均表示假整型和指针间的强转地址的本质是一个编号所以可以
//整型转换为指针
//缺点在绝大多数情况下是不安全的除非你确切知道这个整数表示的内存地址是有效的
int number 1234;
int *ptr (int *)number;//指针转换为整型通常用于获取指针的内存地址
//缺点如果在64位系统上将指针转换为32位整数如 int可能会导致数据丢失。因此建议使用 intptr_t 或 uintptr_t 类型它们在 stdint.h 头文件中定义可以确保适当的大小来存储指针值
int *ptr number;
int address (int)ptr;关于intptr_t和uintptr_t可以查看intptr_t、uintptr_t数据类型的解析 不同类型的指针间的强转
//不同类型的指针间的强制类型转换
char s a;
char* ptr1 s;
int* ptr2 (int*) ptr1;
显示类型转换的缺点
可能导致数据丢失当从一个较大的数据类型转换为一个较小的数据类型时可能会丢失数据。例如将 double 转换为 int 时小数部分会被截断
double d 3.14; int i (int)d; // i 3, 小数部分丢失
降低代码可读性频繁使用显式类型转换会使代码变得难以阅读和理解尤其是当类型转换逻辑复杂时
float f (float)((int)doubleValue * 2.0);
增加错误风险进行类型转换时容易忽略一些潜在的错误如溢出或数据精度问题导致难以发现的bug
long longValue 1234567890123456789LL;
int intValue (int)longValue; // 可能会溢出
隐式类型转换的缺点 隐蔽的数据丢失将 int 转换为 float 时如果整数的值超过了浮点数的精度范围可能会丢失精度
int i 123456789; float f i; // 可能会丢失精度 难以调试和维护隐式类型转换发生在幕后可能导致意外的结果和难以调试的问题。出错时需要仔细检查代码以确保所有隐式转换都符合预期
//int被转换为size_t当传入的pos 0时,会陷入死循环
void Insert(size_t pos)
{int end 10;// 比较的时候end会隐式类型转换成size_t再比较while (end pos){cout end 挪走 endl;--end;}
} C中的类型转换
基本概念C中通过构造函数和重载可以实现内置类型与自定义类型间、自定义类型间的转换
内置类型-自定义类型借助构造函数隐式类型转换
//单参数的构造函数支持内置类型隐式转换成自定义类型
string s1 111111;
const string s2 11111;
自定义类型-内置类型重载某个类型operator 类型名
class A
{
public:operator int(){return _a1 _a2;}
private:int _a1 1;int _a2 2;
};int main()
{A aa;int a aa;int b (int)aa;cout a endl;cout b endl;return 0;
} 自定义类型-自定义类型借助构造函数进行隐式类型转换initializer_list和容器间
C中的类型转换操作符
基本概念C依然兼容C语言的两种类型转换方式但是为了加强类型转换时的可视性C引入了四种类型转换操作符它们是一些进行类型转换时的命名建议并不强制
static_cast
基本概念进行有关联的类型间的隐式类型转换编译时进行也叫静态转换
int main()
{//C的隐式类型转换明显double d 12.34;int a1 static_castint(d);cout a1 endl;//12//C语言的隐式类型转换不明显int a2 d;cout a2 endl;//12return 0;
}
reinterpret_cast 音标riːɪnˈtɜːrprət
基本概念进行强制类型转换不进行类型检查
int main()
{int a 12;// int* p static_castint*(a); 报错,int和int*不是两个相关的类型int* p reinterpret_castint*(a);cout p endl;return 0;
}const_cast
基本概念删除对象的const属性
int main()
{const int a 10;int* p const_castint*(a); // 去除const属性*p 20; // 尝试修改值cout a endl;//a 10cout *p endl;//*p 20return 0;
} 对比监视列表和控制台可以发现虽然在内存中a的值变为了20但是打印时a仍为原来的10这是因为编译器知道const修饰的变量不会被修改那么编译器在编译阶段就会对其优化即编译器会将常量的值直接内联到使用该常量的地方而不是每次都访问内存中的存储位置这一优化技术称为“常量折叠”或“常量传播” 补充const修饰的局部变量仍然存放在栈上修饰的全局变量才放在常量区中 volatile关键字 基本概念用于指示编译器不对变量进行优化带入上述代码再试一试即可 volatile const int a 10;//表示不会对a进行优化 结论const_cast和reinterpret_cast都是强制类型转换const_cast的第一个例子中的a去掉const修饰也能const_cast也能正常使用且a打印时也为20但是单独将const_cast拿出来就是因为可能出现因为编译器对const修饰的变量进行优化而导致的内存可见性 赋值兼容
基本概念有继承关系的派生类与基类之间所遵循的赋值规则包括向上和向下转型
向上转型派生类对象赋值给基类对象发生切片切片 ! 类型转换、派生类的指针/引用赋值给基类的指针/引用通常情况下都支持即这两种情况正常情况下都是可以支持的
#include iostream
using namespace std;class A
{};class B : public A
{};int main()
{//向上转型B bb;A aa bb;//派生类对象直接赋值给基类对象发生切片A* ptr bb;//派生类对象的指针可以直接赋值给基类对象的指针B cc bb;A str cc;//派生类对象的引用可以直接赋值给基类对象的引用return 0;
}向下转型基类对象赋值给派生类对象除非有相关的构造函数、否则即使是强转也转不了、基类对象的指针/引用赋值给派生类对象的指针/引用可以通过强转实现但有越界风险需要得到控制 //有相应的构造函数才能实现基类对象到派生类对象间的转换
#include iostream
using namespace std;class A {
public:int baseData;A() : baseData(0) {}A(int data) : baseData(data) {}
};class B : public A {
public:B() {};// 自定义构造函数实现基类到派生类的转换B(const A a) : A(a) {cout hello endl;}// 自定义赋值运算符实现基类到派生类的转换B operator(const A a) {cout world endl;return *this;}
};int main() {A aaa(10);B bbb;bbb aaa; // 使用自定义赋值运算符B bbb2 aaa; // 使用自定义构造函数return 0;
}dynamic_cast
基本概念为了能控制向下转型时的越界问题、C提供了dynamic_cast类型转换操作符dynamic_cast会在转换前检查是否能转换成功可以转换就转换、不能转换就返回0
#include iostream
using namespace std;class A
{
public:virtual void f() {}int _a 0;
};class B : public A
{
public:int _b 1;
};void fun(A* pa)
{// 向下转换父-子// pa指向子类对象转回子类是安全的// pa指向父类对象转回子类是不安全的存在越界的风险问题// 不安全//B* pb (B*)pa;// pa指向子类对象转回子类正常转换// pa指向父类对象转回子类转换失败B* pb dynamic_castB*(pa);if (pb){cout pb endl;cout pb-_a endl;cout pb-_b endl;}else{cout 转换失败 endl;}
}int main()
{A a;B b;fun(a);//父类转为子类fun(b);//子类转为子类return 0;
}
注意事项dynamic_cast在使用时基类要有虚函数有就行
~over~