C++语言
—— 面向对象的程序设计语言参考教材:
,C++程序设计,
和克智 编著 西安交通大学出版社出版
The C++ Programming Language
by Bjarme Stroustrup 高等教育出版社影印版第 1章 绪论
1.1 C++语言的发展和特点
1.2 面向对象的程序设计面向对象的程序设计( Object-Oriented Programming,简称 OOP) 是在继承和发展了结构化程序设计而产生的一种新的程序设计思想,它是通过模仿人类建立现实世界模型的方法(包括概括、分类、抽象和归纳)进行软件开发的一种思想体系。
OOP 语言必须具有 4 种对象化特性:抽象性、封装性、继承性和多态性。
1.2.1 抽象和封装 ——对象抽象 ( Abstraction)是指将具体事物一般化的过程。对具有特定属性及行为特征的目标进行概括,从中提取这一类目标的共性并从通用性的角度描述其共有的属性和行为特征。抽象包括两方面的内容:数据抽象 —— 某类目标的公共属性;
代码抽象 —— 某类目标共有的行为特征。
在 C++ 语言中,对目标进行抽象的结果是生成一个数据结构,该数据结构中包含有对目标的数据抽象和代码抽象。这样的数据结构就叫做 类 ( Class)。类就是 封装 ( Encapsu-
lation)的具体实现。
类是对一类目标特性的结构性描述,而 对象 ( Object)则是类的一个 实例 ( Instance),即对象是既包含有数据( 属性,
Attribute)又包含对数据进行操作的代码( 方法,Method)
的一个逻辑实体。
1.2.2 派生和继承派生 ( Deriving) 是指由基本类导出子类的过程。用来派生子类的类叫做基类,派生出的子类叫做派生类。派生是可以无限进行下去的。
继承 ( Inheritance) 是指一类对象获取另一类对象之特性的过程,它是通过派生来实现的。一般讲,派生类继承了基类的所有特性(属性和方法)。
由于派生类继承了基类中的所有特性,所以在派生类中只需添加其特有的特性即可。这就为代码重用提供了坚实的基础。
1.2.3 多态性访问某个对象的一个方法这一过程叫做向对象发送一个 消息
( Message)。对象的工作是通过消息来激发的,对象之间也是通过消息来相互联系的,即请求其他对象做什么或响应其他对象的请求均是通过发送和接收消息来实现的。
同一个消息被不同的对象所接收时,可能导致完全不同的行为,这种现象就叫做 多态性 ( Polymorphism)。多态性的重要性在于允许同一类体系中的对象以各自的不同方式响应同一消息。这就是所谓的“同一接口,多种方法”。
1.3 C++程序的结构
/* This program demonstrates the construction of a
C++ program file */
#include <iostream.h>
int main()
{
cout << "i = "; // Display a prompt
int i; // Declare variable i
cin >> i; /* Get value for i */
cout << "Your number is " << i << endl;
return 0;
}
1.4 基本的输入和输出标准输入流 cin:
cin >> variable < >> variable...>;
其中,符号,>>”叫做 提取 运算符,它的作用是从输入流 cin
(缺省为控制台)中获取一个与变量 variable 之类型相匹配的值,并将该值赋给变量 variable。
例:
cin >> i;
cin >> x >> y >> z;
注意这后一种用法:在响应串联方式的输入时,所输入的各数值必须用 空白字符 (空格键,Tab 键或回车键)分隔开来。
标准输出流 cout:
cout << expression < << expression… >;
其中,符号,<<”叫做 插入 运算符,它的作用是向输出流 cout
(缺省为控制台)中传递表达式 expression 的值。
例:
cout << 2 * 3;
cout << 2 << " " << 3;
注意:在串联方式输出中,各表达式常常需要人为地加上某些分隔符号,比如上面第二个输出中实际上是输出了 3 个常量:
2,3 以及由两个空格构成的字符串常量,字符串常量在这里起到分隔两个数值的作用。若无该字符串常量,则输出将变成:
23
第 2章 数据和表达式
2.1 C++语言的词法符号
2.2.1 关键字关键字 ( Key Word)是 C++ 语言的保留字,它们在程序中有着特定的含义。由于随着 C++ 语言标准的不断更新,加之各种具体实现均有不同程度的扩充,一个 C++ 编译器常常规定了 100 多个关键字。因此,这里就不再一一列出。
2.1.2 标识符标识符 ( Identifier) 是程序员为程序中的一些要素 —— 比如,
变量、函数等 —— 所起的名字。 C++ 语言规定标识符可以由字母、数字和下划线组成,且起始字符不得是数字。
例:
i j k MyStr Binary_Tree _123
以下的标识符为非法的:
2_Tree // 起始字符非法
chr$ // 含有非法字符 $
struct // 关键字
C++ 语言是大小写敏感语言,所以以下均是一些合法的、且是不同的标识符:
Friend FRIEND fRIEND frienD
2.1.3 标点符号
C++ 语言中共有 9 种标点符号:
# ( ) { },;,,..
2.1.4 分隔符分隔符是用来分隔词法符号的。在 C++ 语言中,标点符号和运算符均可以用做分隔符,空白字符则是最常用的分隔符。
另外,C++ 编译器会将注释当作空白字符对待,因此,注释也可以用做分隔符。
2.2 基本数据类型
C++ 是编译型语言,因此所有数据均具有某种 数据类型
( Data Type)。数据类型规定了数据的存储需求以及对它们实施的操作。基本数据类型是 C++ 语言预定义的数据类型,
以后将要介绍的数组、指针、结构、联合、枚举和类等导出类型则是由基本数据类型构造而成的。
数据类型 名称 长度 ( bit ) 取值范围
c h a r 字符型 8 - 128 ~ 127
in t 整型 16 - 327 68~ 327 67
f loa t 实型 32 3.4 E - 38~ 3.4E 38
dou ble 双精度型 64 1.7E - 308 ~ 1.7E 308
v oid 无值型 0 无值
C++ 还为基本数据类型预定义了 4 个类型修饰前缀,它们分别是:
short // 短整型,仅修饰 int
signed // 有符号,修饰 char,int
unsigned // 无符号,修饰 char,int
long // 长型,不得修饰 char
注意:当用修饰前缀来修饰 int 时,允许省略关键字 int 。另外,关键字 signed 和 unsigned 还可以与 long 及 short 组合起来修饰整型数据。
例:
unsigned long ul; // ul 被说明成一个无符号长整型量
long double Huge; // Huge 被说明成一个长的双精度
// 型量,其值可达 3.4E4932
几点说明:
1,除了 long 修饰前缀通常将其所修饰的量之取值范围扩大一倍外,其他的修饰前缀并不扩大所修饰量的取值范围,只改变取值的起止点。例如,signed int 型量的取值为 -32768~
32767,而 unsigned int 型量的取值为 0~65535; signed
char 型量的取值为 -128~127,unsigned char 型量的取值为
0~255。
2,所有的编译器均缺省地将无修饰前缀的 int 处理成 signed
int,而对无修饰前缀的 char,不同的编译器的处理方式不尽相同,有的处理成 unsigned char,有的处理成 signed char。
3,所有的实型数据都是有符号的。
4,在 16 位系统中,short 和 int 型数据无本质区别,它们的长度都是 16 位二进制位,取值范围均为 -32768~32767。但在 32 位系统中,int 的长度为 32,而 short 的长度仍为 16。
2.3 常量
2.3.1 数值常量数值常量又分整型数值常量和实型数值常量。
整型数值常量有十进制、八进制和十六进制 3 种表示方法。
十进制整型常量的表示形式与日常数学相同;八进制整型常量由字符 0~7 组成,起始字符必须是 0 ;十六进制整型常量由字符 0~9 及 a~f 组成,起始的两个字符必须是 0x,其中,
字母字符大小写意义相同。
例:
123 // 十进制表示的壹百贰十叁
0173 // 八进制表示的壹百贰十叁
0x7b // 十六进制表示的壹百贰十叁实型数值常量仅用十进制表示,又分一般表示形式和指数表示形式。
例:
3.14159 // 一般表示形式
314159e-5 // 指数表示形式说明:
数值常量也具有各自的数据类型,其数据类型由其值自动确定。
例:
123 // signed int
34567 // unsigned int
0x56789 // signed long int,( 354185)
C++ 语言规定,允许在整型数值常量后缀以 u 或(和) l (大小写无关)来人为指定其数据类型。
例:
123L // long int
5ul // unsigned long int
2.3.2 字符常量字符常量由单个字符构成,其基本表示形式为一对单引号括起来的一个字符。
例:
'a' 'M' '5' '$' ' '
C++ 语言中还有一种所谓 转义序列 ( Escape sequence) 的字符常量表示形式,其表示方式为转义字符,\”后跟一个无前缀 0 的八进制或十六进制常量,常量的值为欲表示之字符常量的 ASCII 码。
例:
'A' '\101' '\x41'
均表示字符常量 A。
几个特殊的转义字符:
\a // 响铃
\b // 退格
\f // 换页
\n // 新行
\r // 回车
\t // 水平制表符
\v // 垂直制表符
\\ // 反斜杠(,\”)
\' // 单引号(,'”)
\" // 双引号(,"”)
2.3.3 字符串常量字符串常量是由一对双引号括起来的字符序列,例如:
"The string"
注意,C++ 语言采用的是所谓的 ASCIIZ 串,即在串中不包含长度信息,而用一个 ASCII
值为 0 的字符来标识串的结束位置。因此,串所占用的存储空间比其实际字符个数要多一个字节。例如:上述字符串常量所占的内存如右图所示。
0x54
0x68
0x65
0x20
0x73
0x74
0x72
0x69
0x6E
0
0x67
2.2 变量及其说明变量就是其值可变的量。一个变量是一块用标识符(叫做变量名)所标识的存储单元,用于存放可由程序修改的值。
C++ 语言中的变量必须“先定义,后使用”。定义变量也叫做 说明 ( Declare)变量,说明变量的一般形式为:
<storage> type var_name <,var_name...>;
其中,storage 为变量的存储类(将在第 4章介绍); type 为数据类型; var_name 为标识符,即程序员为变量所取的名字。
例:
int i,j;
char ch;
double dfResult;
变量具有 4 种基本属性:
1,用变量名标识;
2,占据一定的存储单元;
3,有且仅有一个值;
4,新值将取代旧值。
00
10
0000 0010
0011 0111
02
37 }i2000
2.5 基本运算符和表达式
2.5.1 基本运算符
2.5.1.1 算术运算符
-
+ - * / %
其中:除了模除运算符仅能用于 int 和 char 型数据外,其他运算符可以用于任何基本数据类型。
应当说明的是,当除法运算符的两个操作数均为 int 和 char
型数据时,则运算的结果(即商)为一个 int 型值,小数部分自然丢失。另外,算术运算还存在溢出问题(参见下例)。
注,除法溢出将导致程序的异常终止 。
#include <iostream.h>
int main()
{
int i,j;
i = 32767;
j = i + 1;
cout << "i = " << i << '\t' << "j = " << j << '\n';
return 0;
}
该例的预期输出应为:
i = 32767 j = 32768
而实际的输出结果则为:
i = 32767 j = -32768
这是由于溢出而造成的。
整数 32767 的二进制形式为:
0111 1111 1111 1111
加 1 后变为:
1000 0000 0000 0000
这正是 -32768 的二进制补码。
2.5.1.2 关系运算符
< <= > >= == !=
从理论上讲,关系运算的结果应当是一个逻辑值(“真”或
“假”)。而 C++ 语言中不存在逻辑值,所以关系运算的结果或者是一个非零值(通常为 1,代表逻辑真),或者是零
(代表逻辑假)。由于 C++ 关系运算的结果为一整型值,所以可以将运算结果用于算术运算中。
例:
3 <= 5 // 结果为 1
(3 > 5) != 0 // 结果为 0
(3 < 5) + 1 // 结果为 2
2.5.1.3 逻辑运算符
! && ||
1,逻辑非 !
逻辑非也叫逻辑取反,该运算符为一元运算符。当操作数的值为零时,逻辑非运算的结果为一个非零值(通常为 1);
否则为零。
2,逻辑与 &&
当两个操作数的值均不为零时,逻辑与运算的结果为一个非零值(通常为 1);否则为零。
3,逻辑或 ||
当两个操作数的值均为零时,逻辑或运算的结果为零;否则为一非零值(通常为 1)。
2.5.1.4 位运算符位运算符是对操作数按二进制位进行处理的运算符。因此其操作数只能是 int 或 char 型的数据。
~ & | ^ << >>
为下面介绍的方便,设有以下两个变量:
unsigned char c,d;
并设它们的值分别为 135 和 43,则它们的二进制形式为:
c 1000 0111
d 0010 1011
1,按位取反 ~
按位取反运算符是一元运算符,它将其操作数逐位取反,即将 0 变为 1;将 1 变为 0。比如,~c 的结果为 0111 1000,
即十进制的 120。
2,按位与 &
c & d 的结果为 0000 0011,即十进制的 3。
c 1000 0111
d 0010 1011
c & d 0000 0011
3,按位或 |
c | d 的结果为 1010 1111,即十进制的 175。
c 1000 0111
d 0010 1011
c | d 1010 1111
4,按位异或 ^
c ^ d 的结果为 1010 1100,即十进制的 172。
c 1000 0111
d 0010 1011
c ^ d 1010 1100
5,按位左移 <<
运算符,<<”将其左操作数左移右操作数所规定的位数,移空的位补以 0。例如,d << 1 的结果为 0101 0110,即十进制的
86。而 d << 1 的结果为 1010 1100,即十进制的 172。可以证明,将一个整数左移 n 位,其结果为将该数乘以 2n。 所以在程序中常用按位左移快速地进行乘法运算。
6,按位右移 >>
运算符,>>”将其左操作数右移右操作数所规定的位数,移空的位补以 0。例如,c >> 1 的结果为 0100 0011,即十进制的
67。可以证明,将一个整数右移 n 位,其结果为将该数整除以 2n。 所以在程序中常用按位右移快速地进行除法运算。
注意:按位左移运算符与插入运算符同形、按位右移运算符与提取运算符同形。这种同一符号表示不同运算的现象在 C++
语言中非常普遍,编译器会自动根据上下文来识别不同的符号。
2.5.1.5 sizeof 运算符
sizeof 运算符是一个一元运算符,它的运算结果为操作数按字节计的大小。其用法为:
sizeof(type) 或 sizeof(var)
例:
sizeof(long) // 结果为 4
int k;
sizeof(k) // 结果为 2
2.5.2 表达式表达式是将常量、变量用运算符连起来的式子。
例:
3 * a + 4 / b
x1 = (-b + sqr(b * b - 4 * a * c)) / (2 * a)
x
5
任何一个表达式都有一个值,该值就是表达式中各运算符的最终运算结果。对于单一变量或单一常量这样的特例表达式,其值就是变量或常量的值。