初始化和赋值进行的转换
这里提到的三种潜在的数制转换问题分别是
1.较大的浮点类型转为较小的浮点类型,会导致精度下降,比如double–>double,值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的
#include<iostream>
//#include<limits>
//#include<cfloat>
using namespace std;
int main()
{
double a = 10.0 / 3.0;
float b = 10.0 / 3.0;
const float million = 1.0e6;
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << a* million << endl;
cout << b* million << endl;
cout << a * million* million << endl;
return 0;
}
3333333.333333
3333333.250000
3333333333333.333496
可以在cfloat这个头文件中看到,float的最小有效位数为6位,
double为15位,通过上面的例子可以看到,
float在第七位小数之后出现了错误,但是double直到第十五位之后才出现错误
2.将浮点转换为整型,这种情况很常见,小数部分会丢弃
3.将较大的整形转换为较小的整形,比如long->short
以 {}方式进行转换
这种方式不允许把精度高的转换位精度低的
表达式中的转换
这里书上总结了很多,一共分为两类
- 自动转化,在bool char unsigned char,signed char, short出现时,自动转换为int,这被称为整型提升
- 在不同类型的的变量进行运算时,也会进行转化吗,总结成一句话就是,把精度低的变量转换成精度高的变量进行计算
强制转换
之前我们常见的作法就是
(typeName) value 或者 typeName(value)
后来C++11 引入了四种强制类型转换运算符,可以根据目的选择一个适合的运算符,而不是使用通用的类型转换。这只出了进行类型转换的原因,并让编译器能够检查程序的行为是否与设计者想法相吻合
dynamic_cast
#include<iostream>
using namespace std;
class Low
{
public:
int a;
};
class High : public Low
{
public:
int b;
};
int main()
{
High* ph = new High;
Low* pl = dynamic_cast<Low *>(ph); //允许
Low* p2 = ph; //允许
Low* p3 = new High;
High *ph1 = p3; //编译不允许,因为子类指针不能直接指向父类空间
High* ph2 = (High *)p3; //强制转换之后,编译允许
High* ph3 = dynamic_cast<High*>(p3);//采用C++11 编译不允许
return 0;
}
上面这种转换,仅当Low是High的可访问基类时,才能进行,那么什么是可访问基类呢?
参考下面这个博客 https://www.cnblogs.com/zhaoyl/p/4966865.html
const_cast
这种转换,只能改变值为const 或者 volatile,关于const和* 可以参考我之前的博客
https://blog.csdn.net/qq_36437446/article/details/103099507在这里的第四部分
如果有一个值,大多数时是常量,有时又是可以修改的,在这种情况下,可以将值声明为const,当需要修改的时候,使用这种转换。
#include<iostream>
using namespace std;
class Low
{
public:
int a;
};
class High : public Low
{
public:
int b;
};
int main()
{
High bar;
bar.a = 10;
const High* pbar = &bar;
//pbar->a = 11; //这里编译时通不过的,因为pbar指向一个const 的High型数据
High* pb = const_cast<High*>(pbar);
pb->a = 100;
//const Low* p1 = const_cast<const Low*>(pbar); //不允许,因为尝试修改变量类型从High *到Low *
return 0;
}
还有一点需要注意
#include<iostream>
using namespace std;
void change(const int*, int);
int main()
{
int pop1 = 100;
const int pop2 = 200;
cout << "pop1:" << pop1 << " pop2:" << pop2 << endl;
change(&pop1, -20);
change(&pop2, -20);
cout << "pop1:" << pop1 << " pop2:" << pop2 << endl;
return 0;
}
void change(const int* pt, int n)
{
int* pc;
pc = const_cast<int*>(pt);
*pc += n;
}
pop1:100 pop2:200
pop1:80 pop2:200
这里为什么pop2的值没有被修改呢,因为虽然无法通过pt进行修改,因为pt 的类型是指向const int型数据的指针,但是通过const_cast取消了pt的const属性,所以pop1得以修改,但是因为pop2这个值本身就是const,他是不可被修改的
这里我理解的也不是太好,只是先记住了,以后相同了,再回来解释
static_cast
还是上面的High 和 Low类
High bar;
Low blow;
High *pb = static_cast<High *>(&blow) //OK
Low * pl = static_cast<Low *>(&bar) //ok
如果这里有一个独立的类A
A * a = static_cast<A *>(&bar) //不允许
reinterpret_cast
这种转换适用于依赖于实现的底层编程技术,目前我还没有遇到股,这里不进行介绍