C++常用数据类型转换的区别

时间:2021-10-26 20:19:27

C++常用数据类型转换

1.隐士类型转换
short a = 2;
int b = a;
short是两字节,int是四字节,由short型转成int型是宽化转换(bit位数增多),编译器没有warning
宽化转换(如char到int,int到long long,int到float,float到double,int到double等)构成隐式转换,编译器允许直接转换。 
2. 显示转换:
如果将以上转换关系交换一下
double b = 10000.666;
int a = b;
double是八字节,int是四字节,由double型转成int型是窄化转换(bit位数减少),这样的转换编译器就会报warning ,
因为这样的转换可能会发生数据丢失。

在C语言中我们常常会用到显示的数据类型转换来解决上述的warning,如下:
double b = 10000.666;
int a = (int)b;
像这种显式的类型转换可以强制将b变量的double类型转换为int类型,在进行数据运算,避免了warning。
但是这种显式的强制类型转换会存在一些问题,举一个简单的例子:
我们定义一个基类Base , 再有一个派生类Derived继承基类。
在看例子之前我们先了解一下继承关系下的赋值兼容规则
(1)子类对象可以赋值给父类对象 。
(2)父类对象不能赋值给子类对象。
(3)父类的指针和引用可以指向子类对象。
(4)子类的指针和引用不可以指向父类的指针和引用。

C++常用数据类型转换的区别
下面我们来看这个例子:
#include <iostream>
using namespace std;

class Base
{
public:
Base()
{
cout << "Base()" << endl;
}
virtual ~Base()
{
cout << "~Base()" << endl;
}
};


class Derived:public Base
{
public:
Derived()
{
cout << "Derived()" << endl;
}
~Derived()
{
cout << "~Derived()" << endl;
}
};

上述代码定义一个基类和继承的父类,从赋值兼容规则我们可以看到子类的指针和引用不能指向父类。
但是我们用显式的强制类型转换就可以完成。我们来看一下:

C++常用数据类型转换的区别
C++常用数据类型转换的区别C++常用数据类型转换的区别


这种方法虽然完成了类型转换,但是这种强制类型转换是不安全的,这个时候一个子类的指针指向的是父类对象,
当用这个指针去操作内存数据时就会很危险出现越界访问(访问不属于自己应该访问的内存)等问题。
这时我们C++中引入了类型转换的新方法,这种转换方法可以实现安全转换,避免不安全的转换的问题。

static_cast <new_type> (expression)  ----- 不同数据类型的指针之间的转换 。也能实现基类和派生类指针之间的转换

Derived* pD = static_cast<Derived*>(&b);

C++常用数据类型转换的区别


//需要注意的是转换格式中被转换的对象必须用小圆括号括起来,当一个表达式对待。
//如上图,虽然也可以完成具有继承关系的指针之间的转换,但是不是最安全的,指针转换结果不为空,
//针对这一问题,dynamic_cast可以很好的解决安全问题
 
dynamic_cast <new_type> (expression)  //具有继承关系的指针或引用之间的转换,是动态转换,更安全,
 //这里类A和类B必须是多态的,包含虚函数
我们用刚才的例子来看一下:

C++常用数据类型转换的区别C++常用数据类型转换的区别

C++常用数据类型转换的区别

我们可以看到这个时候转换的结果是一个空指针,当我们对指针判空的时候就会避免对空指针解引用,也就实现了安全问题。
reinterpret_cast <new_type> (expression) //主要用于不同数据类型的指针之间的转换
const_cast <new_type> (expression)  //就是把常指针或者常引用,转换成非常指针或者非常引用
示例
const int &aa = a;
int &bb = const_cast<int&>(aa);
bb = 4;
----------------------
const int *A = &a;
int *B = const_cast<int*>(A);
*B = 5;