面向对象编程的本质是设计并扩展自己的数据类型。
C++内置的数据类型分为两组:基本类型和复合类型。基本类型包括整数和浮点数;复合类型是在基本类型的基础上构建的数组,字符串,指针和结构。
3.1 简单变量
3.1.1 变量名
- 命名规则
- 名称中只能使用字母,数字,下划线
- 名称第一个字符不能为数字
- 不能使用C++关键字作为名称
- 两个下划线开头/下划线+大写字母开头的也不可以,这样的名称是留作系统使用
3.1.2 整型
- C++ 的基本整型分别是:char,short,int,long和C11新增的long long;每种类型都有符号版本和无符号版本
3.1.3 整形short,int,long和long long
- short是short int的简称,而long是long int的简称
- sizeof
返回数据类型占用内存长度 - #include
定义了符号常量来表示类型限制 - #define
该指令的工作方式类似文本编辑器或字处理中的全局搜索并替换命令,它之查找独立的标记(单独的单词),跳过单词内部嵌入的搜索内容;C++创建符号常量的方法一般使用const,不会经常使用#define,但在C++中仍会用到#define - 可以使用表达式对变量赋值,前提是表达是已经定义过的
- C++赋值方式:int wrens(432);
- C++11标准允许等号、大括号来初始化变量,例如:
大括号初始化器是C++专有,使变量初始化方式趋于平凡int emus = {7}; int rheas = {12}; int rocs = {}; // set rocs to 0 int psychics{}; //set psychice to 0
3.1.4 无符号类型
- 创建无符号数据类型,只需要使用关键字
unsigned
来修饰声明即可:unsigned short change;
- 当超出数值类型能够表示的范围时,其实际表示的值需要根据计算机系统计算规则来计算
3.1.5 选择整型类型
- 数据类型声明没有特殊需求,一般使用int;如果变量表示的整数大于16位整数值,建议使用long,方便在程序移植时;无符号数可以表示现实生活中不会是负数的数据比如人口;short比int小,可以在需要节省内存的时候使用;只需要一个字节的,可以使用char
3.1.6 整型字面值
-
C++能够以三种不同的计数方式书写整数:基数为10、基数为8、基数为16;且使用前一(两)位来标识基数。如果第一位为1-9,则基数为10;如果第一位是0,第二位是1-7,则基数为8;如果前两位为0x/0X,则基数为16。这些书写方式仅仅是为了表达方便,最终都会以二进制的方式存储在计算机内存中
-
默认情况下,cout以十进制格式显示整数;如果要以十六进制/八进制方式显示,可以特别指明:C++使用控制符
endl
指示cout
重起一行,除此之外还提供了dec
,hex
,oct
分别用于指示cout以十进制、十六进制、八进制格式显示整数,具体用法如下:int a = 42; int b = 42; int c = 42; cout << "a = " << a << ", in decimal. "; cout << hex; cout << "b = " << b << ", in hexadecimal. "; cout << oct; cout << "c = " << c << ", in octal. ";
最终得到的输出如下:
"a = 42 in decimal. " "b = 2a in hexadecimal. " "c = 52 in octal. "
这些控制符都处于std命名空间,只修改了cout的输出方式
3.1.7 C++如何确定常量类型
- C++在面对未知数据类型时,除非有理由存储为其他类型,否则将存储为int类型
3.1.8 char类型:字符和小整数
-
char类型是专门为存储字符设计的,由于很多系统支持的字符数大多不超过128个,可以由一个字节表示,因此虽然char用来表示字符,但也可以用来表示short更小的整型
-
C++对字符使用单引号,对字符串使用双引号
-
“\n”、'\n’在C++中表示换行符
-
ASCII码在一个变量中存储的是数字编号,当打印时,cout将存储的数字编号转换成数字编号对应的字符,cin和cout的这一行为,是由变量类型引导的
-
一定要注意C++中单引号和双引号使用区别:单引号表示一个字符,双引号表示一串字符
-
cout.put()函数显示一个字符
-
在cout.put()函数中,cout表示对象,put()表示成员函数,其中“.”被称为成员运算符
-
转移序列:\
-
换行符\n可以替代endl
-
char默认情况下既不是没有符号,也不是有符号类型,具体要根据C++的实现来决定,这样开发人员可以最大限度地将这种类型与硬件属性匹配起来;如果有必要,可以显式地设置char类型:
char fodo; // 可能是signed,也可能是unsigned unsigned char bar; // unsigned signed nark; // signed
-
wchar_t:宽字符类型。char表示基本字符类型,一般的表示范围为-128到127(signed类型)或者0-255(unsigned)类型,但如果要表示超过这个范围的字符类型,那么就可以使用wchar_t;cin和cout将输入和输出看做是char流,而对于wchar流,应该使用wcin和wcout来进行处理。此外C11新增了长16位的char16_t和长度为32位的char32_t两种无符号数据类型
-
C++支持隐式转换,所有非零值会被转换为true,零值转换为false
3.2 const限定符
- const:当在变量申请时申明该变量为const,那么之后任何试图修改该变量的操作都是不允许的;且应该变量申请时就初始化,如果没有在声明中初始化,那么该值将是不确定的,且无法修改
3.3 浮点数
3.3.1 书写浮点数
- 手写方式或科学计数法方式(科学计数法中数字前面的符号用于表示正负,e后面的正负表示指数缩放)
3.3.2 浮点类型
- ostream库中的setf()函数迫使输出使用定点表示法,防止程序把较大的值切换成科学表示法,并使程序显示到小数点后6位
- 通常cout会删除结尾处的0,而setf会覆盖这一行为,正常显示到小数点后6位;虽然只显示6位,但当float和double分别乘以一百万后,显示的结果会因为精度不同而有所区别
3.3.3 浮点常量
- 程序中书写浮点常量默认为double类型。如果希望是float类型,需要在数字后面加上f/F后缀;long double类型需要加上l/L后缀
3.3.4 浮点数的优缺点
- 浮点数的运算比整数慢
3.4 C++算术运算符
+
-
*
- /:当除数和被除数同时为整数时,除法返回整数结果;当其中一方为浮点数时,除法结果为浮点数
- %:取余/模运算
- 对于float,C++只保证6位有效位
3.4.1 运算符优先级和结合性
- C++遵从代数的计算优先级:先乘除、后加减;乘除是同一优先级,加减是同一优先级;但同一优先级的运算,运算顺序从左到右,比如120 / 4 * 5 = 150
3.4.2 除法分支
- 浮点常量默认情况下是double类型
- 运算符重载:使用相同的符号进行多种操作;C++允许扩展运算符重载
3.4.3 求模运算符
3.4.4 类型转换
- C++有11种整形和3种浮点型
- C++发生类型转换的场景:
- 将一种算术类型赋值给另一种算术类型
- 表达式中包含不同类型时
- 将参数传递给函数时,会进行类型转换
3.4.4.1 初始化和赋值进行转换
当较大的浮点数->较小浮点数,浮点数->整型,较大的整型->较小的整型,都可能存在结果不确定。
3.4.4.2 以{}方式初始化时进行的转换(C11)
C11对类型转换要求更严格:
- 不允许缩窄(变量类型可能无法表示赋给它的值)
- 不允许将浮点型转换为整型
- 不同整型之间的转换或将整型转换为浮点型可能被允许,前提是编译器能正确存储赋给它的值(例如long和int位数一样时)
3.4.4.3 表达式中的转换
表达式中的转换存在两种情况:
- 类型在出现时便自动转换
在计算表达式时,C++会自动将bool,char,usigned char,signed char和short自动转换为int,这种转换被成为整形提升,一个整形提升的例子是:
当计算fowl值时,编译器自动将chickens和ducks转换成int类型,计算出结果后,再将结果从int转换成short。这么做的原因只是因为计算机使用这种类型,计算会更快。short chickens = 20; short ducks = 35; short fowl = chickens + ducks;
- 在与其他类型同时出现在表达式中时自动转换
例如将int和float相加时,当运算涉及两种类型,小的类型会被转换为较大的类型。
-
C11版本类型转换校验表
- 如果有long double,向long double看齐
- 如果有double,向double看齐
- 如果有float,向float看齐
- 如果以上都没有,则执行整形提升
- 如果两个操作数都是有符号的/无符号的,级别低的向级别高的靠拢
- 如果一个有符号,一个无符号,且无符号操作数比有符号操作数级别高,仍然是级别低向级别搞看齐
- 如果有符号类型可以表示无符号所有可能取值,则将无符号转换为有符号类型进行操作
- 否则,将两个操作数都转换为有符号类型的无符号版本
传统C总是将float提升为double
级别就是:long long > long > int > short > signed char; char = signed char = unsigned char, bool级别最低;wchar_t, char16_t, char32_t级别与底层类型相同
3.4.4.4 传递参数时的转换
传递参数时的转换通常由C++汉书圆形控制,也可以取消原型对参数传递的控制
3.4.4.5 强制类型转换
传统强制转换:
(TypeName) value; // C风格
TypeName(value); // C++风格,与C风格区分开,想法是让强制类型转换像函数调用一般
四个强制类型转换运算符:
static_cast<TypeName> (value);
...
...
...
3.4.5 C++11中的auto声明
- auto将接收的变量按照其初始值自动申明该类型数据
- 一般用于复杂类型数据的自动推断,例如:
std::vector<double> scores; std::vector<double>::iterator pv = scores.begin(); // 可以写成: std::vector<double> scores; auto pv = scores.begin();