2.1基本内置类型
2.1.1整型
wchar_t类型用于扩展字符集,比如汉字日语,这些字符集中的一些字符不能用单个char表示
一般地,short类型为半个机器字(word)长,int类型为一个机器字长,而long类型为一个或两个机器字长(在32位机中,long和int类型通常字长是相同的)
1.带符号和无符号类型
当我们把一个超出其取值范围的值赋给一个指定类型的变量时:
对于unsigned类型来说。编译器会先对该值对unsigned类型的可能取值数目求模,然后取所得值。比如8位的unsigned char,其取值范围从0~255.如果赋给超出这个范围的值,那么编译器会取该值对256求模后的值。例如,如果试图将336存储到8位的unsigned char中,则实际赋值为80.
对于unsigned类型来说,负数总是超出其取值范围的其结果是该负数对该类型的取值个数求模后的值。所以,如果把-1赋给8位的unsigned char,那么结果是255
2.1.2浮点型
类型float、double和long double分别表示单精度浮点数、双精度浮点数和扩展精度浮点数。一般float用一个字(32位)来表示,double类型用两个字(64位)来表示,long double用三个或者四个字来表示。
一般,float类型只能保证6位有效数字,double至少可以保证10位有效数字。
2.2字面值常量
20 //十进制
024 //octal 八进制
0x14 //十六进制
以0(零)开头的字面值整数常量表示八进制,以0x或0X开头的表示十六进制。
通过在数值后面加L或者l指定常量为long类型
可通过在数值后面加U或者u定义unsigned类型
在数值后面加f或F表示单精度
在字符字面值前加L就能够得到wchar_t类型的宽字符字面值,如:L’a’
为了兼容c语言,c++中多有字符串字面值都有编译器自动在末尾添加一个空字符(/0)
多行字面值:
在一行的末尾加以反斜线符号可以将此行和下一行当作同一行处理
注意:反斜线符号必须是该行的尾字符------不允许后面有注释或者空格。同样,后继行行首任何空格、制表符都是字符字面值的一部分。
2.3变量
c++是一门静态语言,在编译时会进行类型检查。
在c++中操作是否合法是在编译时检查的,当编写表达式时,编译器检查表达式中的对象是否按该对象的类型定义的使用方式使用。
静态类型检查使得编译器必须能够识别程序中的每个实体的类型
2.3.1什么是变量
左值和右值
(1)左值:左值可以出现在赋值语句的左边或者右边
(2)右值:右值只能出现在赋值语句的右边,不能出现在赋值语句的左边
变量是左值因此可以出现在赋值语句的左边。数字字面值是右值,因此不能被赋值。
一般而言,对象是内存中具有类型的区域
2.3.2变量名
变量名,即变量标识符,可以由字符、数字和下划线组成。变量名必须由下划线和字母开头,并且区分大小写。
2.3.3定义对象
每个定义都是以类型说明符开始。
类型决定了分配给变量的存储空间大小和在其上可以执行的操作。
1.初始化
定义时指定了初始值的对象是已初始化的。c++有两种初始化变量的形式:复制初始化和直接初始化。
int ival(1024);直接初始化
int ival=1024; 复制初始化
初始化是创建变量并给它赋初始值,赋值则是擦出对象的当前值并用新值替代。
2.3.4变量初始化规则
1.内置类型变量的初始化
内置类型变量是否自动初始化取决于变量定义的位置。在函数体外定义的变量都初始化为0.在函数体内定义的内置类型变量不进行自动初始化。除了用作赋值操作符的左操作数,未初始化变量用作任何其他用途都是没有定义的
2.类类型变量的初始化
如果没有提供初始化式,那么会使用默认构造函数。不管变量在哪里定义,默认构造函数都会被使用。
2.3.5声明和定义
变量的定义:用于为变量分配存储空间,还可以为变量指定初始值。
声明:用于向程序表明变量的类型和名字。当定义变量时,我们声明了它们的类型和名字。还可以通过使用extern关键字声明变量而不定义它。
extern int i;//声明但是没有定义
int i; //声明和定义
extern声明不是定义,也不分配存储空间。事实上,它只是说明,变量定义在程序的其他地方。
程序中的变量可以声明多次,但是只能定义一次(而且在使用变量前必须定义或者声明变量)
只有当声明也是定义时,才可以有初始化式,因为只有定义才分配存储空间。初始化式必须有存储空间来初始化。如果声明有初始化式,它被当做是定义,即使声明为extern:
extern double pi=3.1415
2.3.6名字的作用域
c++程序中,每个名字都与唯一的实体相关联,尽管有这样的要求,还是可以再程序中多次使用同一个名字,只要他们在不同的上下文中,且通过这个上下文可以区分该名字的不同意义。
用来区分名字的不同意义的上下文称为作用域。作用域是程序的一段区域
定义在所有函数外部的名字具有全局作用域,可以再程序中的人和地方访问。在main函数中定义,在整个main中都可以访问的,但在main外部不能访问。变量具有局部作用域
定义在for语句中的变量,只能在for语句中使用,它具有语句作用域
名字可以再内部作用域中重新定义。内层作用域重新定义的变量名字,将会屏蔽外层作用域中相同的名字
c++还有另外两种相同级别的作用域:类作用域和命名空间作用域
2.4 const限定符
1.定义const对象
const将一个对象转换成一个常量。 const int bufsize=512
任何尝试修改bufsize的尝试都会导致编译错误
因为常量在定义后就不能被修改,所以定义时必须被初始化
2.const对象默认为文件的局部变量
在全局域中定义非const变量时,它在整个程序中都可以访问。
除非特别声明。在全局域中声明的const变量是定义该对象的文件的局部变量
同过指定const变量为extern,就可以在整个程序中访问const对象
非const变量默认为extern,要使const变量能在其他文件中访问,必须显示地指定它为extern。
2.5引用
引用就是对象的另外一个名字。主要用作函数的形式参数
引用是一种复合类型,通过在变量名前添加“&”符号来定义。不能定义引用类型的引用
1.引用是别名
作用在引用上的所有操作都将作用在该引用绑定的对象上;
当引用绑定到一个对象上后,只要该引用存在,它就保持绑定到初始化时指向的对象。不可能将引用绑定到另一个对象上
2.定义多个引用
可以在一个类型定义行中定义多个引用。必须在每个引用标识符前加“&”;
int &a=b,&c=d;
3.const引用
const引用是指向const对象的引用
const对象可以初始化为不同类型的对象或者初始化为右值.如字面值常量
const int &a=42;
将引用绑定到不同类型对象时
double dval=3.14;
cosnt int &ri=dval;
编译器会把这些代码转化为下面的形式
int temp=dval;
cosnt int &ri=temp;
如果ri不是const,那么可以给ri赋一个新的值,这样做不会修改dval,而是修改了temp,期望对dval修改的人会发现dval并没有被修改。仅允许const引用绑定到需要临时使用的值时避免了这个问题,因为const引用是只读的
非const引用只能绑定到与该引用同类型的对象
const引用可以绑定到不同但是相关类型的对象或者绑定到右值
2.6 typedef名字
typedef定义以关键字typedef开始,后面是数据类型和标识符。标识符或类型名没有引入新的类型,而只是现有数据类型的同义词。
2.7枚举
枚举不但定义了整数常量集,而且还把他们聚集成组。
1.定义和初始化枚举
枚举定义包括关键字enum,其后是一个可选的枚举类型名,和一个用花括号括起来、用逗号分开的枚举成员列表
enum open{input,ouput,append};
默认地,第一个枚举成员为0,后面的每个枚举成员赋值比前一个大1。
2.枚举成员是常量
用来初始化枚举成员的值必须是一个常量表达式。常量表达式是在编译器在编译阶段就能计算出来结果的整型表达式。整型字面值是常量表达式
不能改变枚举成员的值,枚举成员本身就是一个常量表达式,所以可以用于需要常量表达式的任何地方
2.8类类型
当定义类的数据成员时,只能指定该数据成员的类型和名字。
4.访问标号
类的成员函数可以使用类的任何成员,不管其访问级别
类中public部分定义的成员在程序中的任何部分都可以访问。
不是类的组成部分的代码不能访问private
5.使用struct关键字
如果使用class关键字定义类,那么定义在第一个访问标号前的这些成员都是private;如果使用struct关键字,那么这些成员都是public的。
用class和struct关键字定义类的唯一差别在于默认访问级别:默认情况下,struct的成员为public,class的成员为private
2.9编写自己的头文件
头文件一般包含类的定义,extern变量的声明和函数的声明
1.头文件用于声明而不是用于定义
定义只可以出现一次,而声明可以出现多次。
因为头文件包含在多个源文件中,所以不应该含有变量或者函数的定义
对于头文件不应该含有定义这一原则,有三个例外。头文件可以定义类,值在编译时就已经知道的const对象和inline函数。这些实体可以在多个源文件中定义。
在头文件中定义这些实体是因为编译器需要他们的定义来产生代码。
2.一些const对象定义在头文件中
const变量默认是定义该变量的文件中的局部变量,这样设置默认情况的原因在于允许const变量定义在头文件中
当我们在头文件中定义了const变量后,每个包含头文件的源文件都有了自己的const变量,其名称和值都一样。
如果const变量不是常量表达式初始化,那么它就不能定义在头文件中。它应该和其他变量一样,该const变量应该在一个源文件中定义并且初始化。应该在头文件中为它添加extern声明,以使其能被多个文件共享。
2.9.2预处理器的简单介绍
预处理器用指定的头文件的内容替代每个#include
1.头文件经常需要其它头文件
设计头文件时,应该可以多次包含在同一源文件中。我们必须保证多次包含同一头文件而不会引起该头文件定义的类和对象被多次定义。
使头文件安全的做法是使用预处理器定义头文件保护符
2.避免多重包含
预处理器变量的名字在程序中必须是唯一的。任何与预处理器变量相匹配的名字的使用都关联到该预处理器变量
预处理器变量有两种状态:已定义和未定义。#define指示接受一个名字并定义改名字为预处理器变量。#ifndef指示检测指定的预处理器变量是否未定义。如果预处理器变量未定义,那么跟在其后的所有指示都被处理,直到出现#endif
可以使用这些设施来预防多次包含同一头文件
1: #ifndef SALESITEM_H2: #define SALESITEM_H3: //类定义和相关函数
4: #endif
条件指示
#ifndef SALESITEM_H
测试SALESITEM_H是否未定义。如果未定义,那么#ifndef测试成功,跟在#ifndef后面的所有行都被执行,直到发现#endif
3.使用自定义的头文件
如果头文件名包含在尖括号(<>)里,那么认为该头文件是标准头文件。编译器会在预定义的位置集查找该头文件,这些预定义的位置可以通过设置查找路径环境变量或者通过命令来修改。若果头文件名在一对引号里,那么认为它是非系统头文件,非系统头文件查找通常开始于源文件所在的路径