2.5 处理类型
2.5.1 类型别名
类型别名是一个名字,它是某种类型的同义词。好处是让复杂的类型名字变得简单明了、易于理解和使用。
有两种方法定义类型别名:
1.传统的方法是使用关键字typedef:
2. 新标准规定,使用别名声明来定义类型的别名:用关键字using作为别名声明的开始,其后紧跟别名和等号。using SI = Sales_item;
类型别名可以指代复合类型或常量,不要尝试把类型别名替换成本来的样子来理解,很容易理解错误。
类型pstring实际上是类型char*的别名,pstring是指向char的指针。
2.5.2 auto类型说明符
C++11引入了auto类型说明符,用它就能让编译器替我们去分析表达式所述的类型,通过初始值来推算变量的类型,所以auto定义的变量必须有初始值:
如果val1和val2都是double类型,则item的类型就是double。使用auto也能在一条语句中声明多个变量,该语句中所有变量的初始基本数据类型必须一样。auto sz=0, pi=3.14;错误,sz和pi的类型不一致。
引用其实是使用引用的对象,编译器以引用对象的类型作为auto的类型
要在一条语句中定义多个变量,初始值必须是同一类型:
2.5.3 decltype类型指示符
有时希望从表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量,为此,C++11引入了第二种类型说明符decltype,它的作用是选择并返回操作数的数据类型。再次过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。
decltype处理顶层const和引用的方式与auto有些许不同。引用从来都作为所指对象的同义词出现,只要用在decltype处是个例外。
如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内):
如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。
r是一个引用,decltype®的结果是引用类型,如果想让结果类型是r所指的类型,可以把r作为表达式的一部分,如r+0. 如果i是整型,则表达式i=x的类型是int&. 如果表达式的内容是解引用操作(*p),则decltype将得到引用类型。
decltype((variable))的结果永远是引用,decltype(variable)的结果是variable的类型,只有当variable本身就是一个引用时才是引用。
decltype和auto都可以用来推断类型,但是二者有几处明显的差异:1.auto忽略顶层const,decltype保留顶层const;2.对引用操作,auto推断出原有类型,decltype推断出引用;3.对解引用操作,auto推断出原有类型,decltype推断出引用;4.auto推断时会实际执行,decltype不会执行,只做分析。
2.6 自定义数据类型
C++允许用户以类的形式自定义数据类型。
2.6.1 定义Sales_data类型
以关键字struct开始,紧跟着类名和类体(类体部分可以为空)。类体由花括号包围形成一个新的作用域。类内部定义的名字必须唯一,但是可以与类外部定义的名字重复。类体右侧的表示结束的花括号后必须写一个分号,这是因为类体后面可以紧跟变量名以示对该类型对象的定义。一般来说,最好不要把对象的定义和类的定义放在一起。
类数据成员
类体定义类的成员,我们的类只有数据成员。类的数据成员定义了类的对象的具体内容。
定义 数据成员的方法和定义普通变量一样:首先说明一个基本类型,随后紧跟一个或多个声明符。可以为数据成员提供一个类内初始值,没有初始值的成员将被默认初始化。也可以用另一个关键字class来定义自己的数据结构。
2.6.2 使用Sales_data类
添加两个Sales_data对象
Sales_data对象读入数据
输出两个Sales_data对象的和
2.6.3 编写自己的头文件
类一般不定义在函数体内。为了确保各个文件中类的定义一致,类通常被定义在头文件中,而且头文件的名字应与类的名字一样。
预处理器概述
头文件也经常用到其他头文件的功能,确保头文件多次包含仍能安全工作的常用技术是预处理器。
之前用到了一项预处理功能#include,当预处理器看到#include标记时就会用指定的头文件的内容代替#include。