C++语言定义的标准转换
标准转换
C++ 语言定义其基础类型之间的转换。 它还定义指针、引用和指向成员的指针派生类型的转换。 这些转换称为“标准转换。
1. 整型提升
整数类型的对象可以转换为另一个更宽的整数类型(即,可表示更大的一组值的类型)。 这种扩展类型的转换称为“整型提升”。 利用整型提升,您可以在可使用其他整数类型的任何位置将以下项用于表达式:
char和short int类型的对象、文本和常量枚举类型
int位域枚举器
C++ 提升是“值保留”。 即,提升后的值一定与提升前的值相同。 在值保留提升中,如果 char 可以表示原始类型的完整范围,较短的整数类型的对象(如 int 类型的位域或对象)将提升到 int 类型。 如果 int 无法表示完整范围的值,该对象将提升到 unsigned int 类型。 尽管此策略与 ANSI C 中使用的相同,但值保留转换不保留对象的“符号”。
值保留提升和保留符号的提升通常会生成相同的结果。 但是,如果提升的对象是以下项之一,它们可能生成不同的结果:
/、
%、/=、%=、<、<=、> 或 >= 的操作数这些运算符依赖于用于确定结果的符号。 因此,当值保留和符号保留提升应用于这些操作数时,它们将生成不同的结果。
>> 或 >>= 的左操作数
当执行移位运算时,这些运算符会区别对待有符号的数量和无符号的数量。 对于有符号的数量,将数量右移会导致符号位传播到空出的位位置。 对于无符号的数量,空出的位位置将由零填充。
重载函数的参数,或重载运算符的操作数(取决于该操作数的用于参数匹配的类型的符号)。
2. 整型转换
整型转换在整型之间执行。 整型包括 char、int 和 long(以及这些类型的 short、signed 和 unsigned 版本)
(1)有符号转换为无符号
有符号整数类型的对象可以转换为对应的无符号类型。 当这些转换发生时,实际位模式不会更改;但是,数据的解释会更改。
// conve__pluslang_Converting_Signed_to_Unsigned.cpp
// compile with: /EHsc
#include <iostream> using namespace std;
int main()
{
short i = -;
unsigned short u; cout << (u = i) << "\n";
}
// Output: 65533
在前面的示例中,signed short i 被定义和初始化为负数。 表达式 (u = i) 导致 i 在为 赋值前转换为 uunsigned short。
(2)无符号转换为有符号
无符号整数类型的对象可以转换为对应的有符号类型。 但是,如果无符号对象的值在有符号类型表示的范围之外,则此类转换可能导致数据错误解释,如以下示例所示:
// conve__pluslang_Converting_Unsigned_to_Signed.cpp
// compile with: /EHsc
#include <iostream> using namespace std;
int main()
{
short i;
unsigned short u = ; cout << (i = u) << "\n";
}
//Output: -3
在前面的示例中,u 是一个 unsigned short 整数对象,必须将其转换为有符号的数量来计算表达式 (i = u)。 由于其值无法在 signed short 中正确表示,因此数据被错误解释。
3. 浮点转换
浮动类型的对象可以安全地转换为更精确的浮点类型,也就是说,转换不会导致基数丢失。 例如,从 float 到 double 或从 double 到 long double的转换是安全的,并且值保持不变。
如果浮点类型的对象位于低精度类型可表示的范围中,则还可转换为该类型。 (有关浮点类型的范围,请参阅浮点限制。) 如果原始值不能精确地表示,则可将其转换为下一更高或更低的可表示值。 如果此类值不存在,则结果是不确定的。
某些表达式可能导致浮点型的对象转换为整型,反之亦然。 当整型对象转换为浮点型且无法正确表示原始值时,结果要么是下一个较大的可表示值,要么是下一个较小的可表示值。
当浮点型的对象转换为整型时,小数部分将被截断。 转换过程中不会进行舍入。 截断意味着,数字 1.3 将转换为 1,–1.3 将转换为 –1。
5、 算术转换
很多二元运算符(在带二元运算符的表达式中有讨论)会导致操作数转换并以相同的方式产生结果。 这些运算符导致转换的方式称为“常用算术转换”。 不同本机类型的操作数的算术转换按下表所示的方式执行。 Typedef 类型的行为方式基于其基础本机类型。
| 其中一个操作数是 long double 类型。 | 另一个操作数将转换为 long double 类型。 |
| 未满足上述条件,并且其中一个操作数是 double 类型。 | 另一个操作数将转换为 double 类型。 |
| 未满足上述条件,并且其中一个操作数是 float 类型。 | 另一个操作数将转换为 float 类型。 |
| 未满足上述条件(没有任何一个操作数属于浮动类型)。 | 整型提升按以下方式对操作数执行:
- 如果其中一个操作数是 |
6. 指针转换
在赋值、初始化、比较和其他表达式中,可以转换指针。
(1)指向类的指针
在两种情况下,指向类的指针可转换为指向基类的指针。
第一种情况是指定的基类可访问且转换是明确的。
基类是否可访问取决于派生中使用的继承的类型。 考虑下图中阐释的继承。

下表显示针对该图阐释的情况的基类可访问性。
由表中可知:
- 直接从派生类指针转换成父类指针,只能有时Public继承,才能合法转换为父类指针;
- 在子类内部, 直接将 (A*)this,即不管继承方式,都可以合法转换使用,且根究A的成员访问属性,以及继承方式访问特定函数。
- 在子子类内部, 因为B private 继承了A, 则限制了再子子C中的访问,因此该情况无效。
| 函数的类型 | 派生 | 从
B* 到 A* 的转换是否合法? |
|---|---|---|
| 外部(非类范围)函数 | Private | No |
| Protected | No | |
| Public | 是 | |
| B 成员函数(在 B 范围内) | Private | 是 |
| Protected | 是 | |
| Public | 是 | |
| C 成员函数(在 C 范围内) | Private | No |
| Protected | 是 | |
| Public | 是 |
第二种情况是,在您使用显式类型转换时,指向类的指针可转换为指向基类的指针。只能访问由基类的属性。
此类转换的结果是指向完全由基类描述的对象部分(即“子对象”)的指针。
以下代码定义了两个类(即 A 和 B),其中 B 派生自 A。 (有关继承的详细信息,请参阅派生类。) 然后定义 bObject、类型 B 的对象和两个指向该对象的指针(pA 和 pB)。
// conve__pluslang_Pointers_to_Classes.cpp
// C2039 expected
class A
{
public:
int AComponent;
int AMemberFunc();
}; class B : public A
{
public:
int BComponent;
int BMemberFunc();
};
int main()
{
B bObject;
A *pA = &bObject;
B *pB = &bObject; pA->AMemberFunc(); // OK in class A
pB->AMemberFunc(); // OK: inherited from class A
pA->BMemberFunc(); // Error: not in class A
}
指针 pA 的类型为 A *,它可解释为“指向类型 A 的对象的指针”。 bObject ( 的成员(如 BComponent 和 BMemberFunc)对类型 B 是唯一的,并且无法通过 pA 进行访问。 pA 指针只允许访问类 A 中定义的对象的那些特性(成员函数和数据)。
7. 指向函数的指针
如果类型 void * 足以保留指向函数的指针,则该指针可以转换为 void * 类型。指向函数的指针可以转化成为void*。
8 指向 void 的指针
指向 void 类型的指针可以转换为指向其他任何类型的指针,但仅适合于显式类型转换(与在 C 中的情况不同)。
指向任何类型的指针可以隐式转换为指向类型 void 的指针。指向类型的不完整对象的指针可以转换为指向 void(隐式)和 back(显式)的指针。 此类转换的结果与原始指针的值相等。 对象被视为是不完整的(如果已声明对象),但未提供足够多的可用信息,无法确定其大小或基类。
指向不是 const 或 volatile 的任何对象的指针可以隐式转换为 void * 类型的指针。
9. 固定和可变指针
C++ 将不会应用从 const 或 volatile 类型到不是 const 或 volatile 类型的标准转换。 但是,任何类型的转换都可以用显式类型强制转换指定(包括不安全的转换)。
指向成员的 C++ 指针(指向静态成员的指针除外)与常规指针不同,二者具有不同的标准转换。 指向静态成员的指针是普通指针,且与普通指针具有相同的转换。
10 null 指针转换
计算结果为零的整数常量表达式
或到某个指针类型的此类表达式强制转换,将转换为称为“null 指针”的指针。 此指针与指向任何有效对象或函数的指针比较的结果肯定不会相等(指向基对象的指针除外,此类指针可以有相同的偏移量并且仍指向不同的对象)。
在 C++11 中, nullptr 类型应优先于 C 样式 null 指针
11 指针表达式转换
带数组类型的所有表达式都可以转换为同一类型的指针。 转换的结果是指向第一个数组元素的指针。 下面的示例演示了这样的转换:
char szPath[_MAX_PATH]; // Array of type char.
char *pszPath = szPath; // Equals &szPath[0].
12 引用转换
对类的引用可在以下情况下转换为对基类的引用:
转换的结果为指向表示基类的子对象的指针。
13 指向成员的指针
指向可在赋值、初始化、比较和其他语句中转换的类成员的指针。
14 指向基类成员的指针
当满足以下条件时,指向基类的成员的指针可以转换为指向派生自基类的类的成员的指针:
从指向派生类的指针到基类指针的反向转换可以访问。
派生类并非以虚拟方式从基类继承。【因为虚拟方式继承,函数属于子类,而非父类】
当左操作数是指向成员的指针时,右操作数必须是 pointer-to-member 类型或计算结果为 0 的常量表达式。 此赋值仅在以下情况下有效:
右操作数是指向与左操作数相同的类的成员的指针。
左操作数是指向以公共但不明确的方式派生自右操作数的类的成员的指针。
15. 整数常量转换
计算结果为零的整数常量表达式将转换为名为“null 指针”的指针。 此指针与指向任何有效对象或函数的指针比较的结果肯定不会相等(指向基对象的指针除外,此类指针可以有相同的偏移量并且仍指向不同的对象)。
以下代码演示了指向类 i 中的成员 A 的指针的定义。 指针 pai 将初始化为 0,因此是 null 指针。
// conve__pluslang_Integral_Constant_Expressions.cpp
class A
{
public:
int i;
}; int A::*pai = ; int main()
{
}
因为:
endl.
C++语言定义的标准转换的更多相关文章
- C++标准转换运算符
C++类型转换在实际编程中会经常使用,其实,本质上对象的类型用来解释(interpret)对象.因为,每个对象都占据一块内存空间,这块内存空间存放了一段二进制数据.通过标记该对象的类型,告诉如何看待这 ...
- C++标准转换运算符reinterpret_cast
C++标准转换运算符reinterpret_cast reinterpret_cast <new_type> (expression) reinterpret_cast运算符是用来处理无关 ...
- C++标准转换运算符 --四种
具体归纳如下: reinterpret_cast 函数将一个类型的指针转换为另一个类型的指针. 这种转换不用修改指针变量值存放格式(不改变指针变量值),只需在编译时重新解释指针的类型就可做到.rein ...
- C语言指针类型 强制转换
关于C语言指针类型 强制转换 引用一篇文章: C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值.不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个 ...
- Java语言定义的线程状态分析
说到线程,一定要谈到线程状态,不同的状态说明线程正处于不同的工作机制下,不同的工作机制下某些动作可能对线程产生不同的影响. Java语言定义了6中状态,而同一时刻,线程有且仅有其中的一种状态.要获取J ...
- 自己定义View Controller转换动画
原文链接 : Introduction to Custom View Controller Transitions and Animations 原文作者 : joyce echessa 译文出自 : ...
- C语言定义数组时使用枚举作为数组的下标 ——c99功能
部分参考了https://blog.csdn.net/wq3028/article/details/76204690 同时在电脑上进行验证 //温度,电磁阀传感器序号,方便数组定位 typedef e ...
- Go语言系列之标准库log
Go语言内置的log包实现了简单的日志服务.本文介绍了标准库log的基本使用. 使用Logger log包定义了Logger类型,该类型提供了一些格式化输出的方法.本包也提供了一个预定义的" ...
- shell编程:定义简单标准命令集
shell是用户操作接口的意思,操作系统运行起来后都会给用户提供一个操作界面,这个界面就叫shell,用户可以通过shell来调用操作系统内部的复杂实现,而shell编程就是在shell层次上进行编程 ...
随机推荐
- 软件开发中 SQL SERVER 任务的用法
在软件开发中,经常性会用到定时任务.这个时候你可能会想到线程.但是事实中,线程方法比较麻烦.容易出错,资源竞争等问题,设计起来让你很头痛. 现在给大家提供一个新的思路,用SQL SERVER 的任务管 ...
- 为什么CNN能自动提取图像特征
1.介绍 在大部分传统机器学习场景里,我们先经过特征工程等方法得到特征表示,然后选用一个机器学习算法进行训练.在训练过程中,表示事物的特征是固定的. 后来嘛,后来深度学习就崛起了.深度学习对外推荐自己 ...
- find和find_if,value_type
find算法:返回 [first,end)中第一个值等于value元素的位置 线性复杂度:最多比较次数:元素的总个数 find函数的最后一个参数,必须是string,float,char,double ...
- 使用GrabCut提取前景图像的示范代码
#include<opencv2/opencv.hpp> bool selectObject = false; cv::Point origin; cv::Rect selection; ...
- N! (大数,优化)
Problem Description 输出N的阶乘.(注意时间限制150ms&&注意不能打表后输出) 打表的定义:在本地主机预先计算出了每个值对应的答案,并把输入和输出的映射直接写入 ...
- asp.net web 服务器端全局定时执行任务
web网站里面,需要每隔1分钟,执行一个任务,并且一直保持这个定时执行状态,可以用如下一个方法: 1,Global.asax里面的 Application_Start ,发生在第一次请求网站的时 ...
- linux学习第一天 (Linux就该这么学) 找到一本不错的Linux电子书,附《Linux就该这么学》章节目录
本书是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材,目前是国内最值得去读的Linux教材,也是最有价值 ...
- List<? extends T>和List<? super T>之间有什么区别?
List<? extends T>表示类型的上界为T,即参数化的类型可能是T也可能是T的子类.<? extends T>被设计用来读数据的泛型,只能读取类型为T的元素. Lis ...
- Python之路(第八篇)Python内置函数、zip()、max()、min()
一.python内置函数 abs() 求绝对值 例子 print(abs(-2)) all() 把序列中每一个元素做布尔运算,如果全部都是true,就返回true, 但是如果是空字符串.空列表也返回t ...
- javase高级技术 - 泛型
在写案例之前,先简单回顾下泛型的知识 我们知道,java属于强变量语言,使用变量之前要定义,并且定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 所谓“泛型”,就是“宽泛的数据类 ...