C++中的类型转换
创始人
2024-03-15 01:31:47
0

文章目录

  • 一、隐式类型转换
  • 二、显式类型转换
  • 三、c++风格的类型转换


一、隐式类型转换

 
隐式类型转换,顾名思义,就是没有明显的声明要进行类型转换,隐式类型转换有可能造成数据精度的丢失,所以通常所做的类型转换都是从size小的数据到size大的数据。
 
我们以数字为例,在程序中见到的所有整形立即数都被当作int类型,所有浮点数立即数都被当作double类型,如下所示:

int main() {auto a = 12.34;auto b = 100;std::cout << typeid(a).name() << std::endl; //doublestd::cout << typeid(b).name() << std::endl; //intreturn 0;
}

在进行加减乘除等基本运算的时候,首先要保证运算符两边是同类型的数据,这时候,编译器会做隐式的类型转换,都是将数据从size小转到size大,这时不会损失数据精度,⚠️同时存在signedunsigned的时候,signed会转换成unsigned。其他的转换借鉴下图:
在这里插入图片描述
对象中包含的隐式转换:

  1. 对象构造的时候使用如果编译器可以找到对象的构造函数,此时也会发生隐式的类型转换,但是通常不希望这种情况发生,可以在构造函数前加explicit关键字进行避免;

 

二、显式类型转换

这个没什么好说的,通过类型强转的方式,程序上能直接指定要转换成何种类型。但是需要注意一点的是,对象也能通过运算符重载函数强转成基本类型。使用方法如下:

class A {
public:explicit A(int ma) : _ma(ma) {}explicit operator double() const {double a = 13.34;return a;}
private:int _ma;
};

 

三、c++风格的类型转换

  1. static_cast
    static_cast类似于强制类型转换,只是是一种tight type check的类型转换,而且是编译时期的类型转换。之所以说他是tight type check是因为static_cast不允许做一些不合理的类型转换,如下所示:
#include 
#include 
using namespace std;
int main()
{int a = 10;char c = 'a';// pass at compile time, may fail at run timeint* q = (int*)&c;  //clang编译通过int* p = static_cast(&c); //编译失败return 0;
}

另外在继承结构中,必须是public继承才能使用static_cast进行类型向上转换,如下所示:

class Base {
};class Derived : private Base { // Inherited private/protected not public
};int main() {Derived d1;Base *b1 = (Base *) (&d1); // allowedBase *b2 = static_cast(&d1); //编译失败return 0;
}

 
2. dynamic_cast
这种转换需要用到RTTI机制,关于RTTI的原理和对象内存布局,见我的另一篇博客C++对象内存布局。
在这里插入图片描述

既然涉及到RTTI,那就必须有虚函数,如果继承结构中没有虚函数,那也就用不了dynamic_cast,dynamic_cast支持downcasting和upcasting,但是指针必须指向的是同一个对象,如果转换失败,dynamic_cast返回nullptr。使用方法如下:

// C++ program demonstrate if there
// is no virtual function used in
// the Base class
#include 
using namespace std;// Base class declaration
class Base {void print(){cout << "Base" << endl;}
};// Derived Class 1 declaration
class Derived1 : public Base {void print(){cout << "Derived1" << endl;}
};// Derived class 2 declaration
class Derived2 : public Base {void print(){cout << "Derived2" << endl;}
};// Driver Code
int main()
{Derived1 d1;// Base class pointer hold Derived1// class objectBase* bp = dynamic_cast(&d1);// Dynamic castingDerived2* dp2 = dynamic_cast(bp);if (dp2 == nullptr)cout << "null" << endl;return 0;
}

 
3. reinterpret_cast
顾名思义,重新解释的意思,这种类型转换将任意一种指针转换成另一种指针,这是一种危险的转换,使用方式如下:

#include 
using namespace std;int main()
{int* p = new int(65);char* ch = reinterpret_cast(p);cout << *p << endl;cout << *ch << endl;cout << p << endl;cout << ch << endl;return 0;
}

 
4. const_cast
const_cast用于将变量的const约束去掉,const_cast并不像想象的那样可以直接修改const变量,const_cast去除掉的一般是指针的约束,使用方法见下:

const int a=10;
int b  = const_cast(a); //这里会编译失败,因为实际上a的const限制是无法去除的
int main(void) {int a1 = 40;const int *b1 = &a1;int *c1 = const_cast  (b1); *c1 = 100;   //此处没有问题,可以通过c1修改a1;*b1 = 1000; //此处编译失败,不能通过b1修改a1;cout << a1 << endl;return 0;
}

如上所示,a1并不是const变量,只是我们定义了一个const指针,我们不能通过这个指针修改a1,但是我们可以把指针的const去掉,然后用去掉const限制的指针来修改a1。
 
const_cast还可以用来在类的const函数中修改成员变量,因为在const方法中的this指针实际上是一个const指针,我们可以用const_cast去掉const限制,然后来修改成员变量,使用方法如下所示:

class student
{
private:int roll;
public:// constructorstudent(int r):roll(r) {}// A const function that changes roll with the help of const_castvoid fun() const{( const_cast  (this) )->roll = 5;}int getRoll()  { return roll; }
};

const_cast是一种比强转更安全的类型转换,比如将const int* 转为int是允许的,但是将const int转为char*是不允许的。
const_cast还可以将volatile约束去掉,如下所示:

int main(void)
{int a1 = 40;const volatile int* b1 = &a1;cout << "typeid of b1 " << typeid(b1).name() << '\n'; //PVKiint* c1 = const_cast  (b1);cout << "typeid of c1 " << typeid(c1).name() << '\n'; //Pireturn 0;
}

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...