C++基础知识

1.1  面向对象程序设计

C++起源于C语言,它既保留了传统的结构化程序设计方法,也支持流行的面向对象程序设计方法。C++C语言的超集,即C++中包含C语言的全部语法特征。

结构化程序设计是面向过程的,其主要思想是将功能分解并逐步求精。在结构化程序设计中,数据与处理数据的算法是相互分离的,这很容易使数据和算法的一致性差。面向对象程序设计具有以下三个主要特征:

1.封装性

封装性是指将数据和算法捆绑成一个整体,这个整体就是对象。描述对象的数据被封装在对象的内部,如果需要存取数据可以通过对象提供的算法来进行操作,而无需知道对象内部的数据是如何表示和存储的,这种思想称为信息隐蔽。C++通过建立用户定义类型——“类”,来支持封装性和信息隐蔽。

2.继承性

继承性是指一种事物保留了另一种事物的全部特征,并且具有自身的独有特征。C++通过继承来支持重用,使程序可以在现有类型的基础上扩展功能来定义新类型。

3.多态性

多态性是指当多种事物继承自一种事物时,同一种操作在它们之间表现出不同的行为。C++通过函数重载、模板、虚函数等来支持多态性。

 

1.2  C++程序的词汇

基本符号是组成语言的最小元素,C++基本符号包括字母(含有大小写字母A~Z52个)、数字(含有0~910个)、特殊符号(含有+ - * / = , . _ : ; ? \ " ' ~ | ! # % & ( ) [ ] { } ^ < >和空格共30个)三类共92个。由这此基本符号组成了以下五类合法的C++词汇,一个C++程序只能由这此词汇组成。

1.关键字

关键字也称为保留字,它是由C++本身预先定义好的一类标识符。每个关键字在C++中都具有特殊的含义并实现一定的功能。不能将关键字再当作其他类型的标识符使用。

1.1  ANSI C标准规定的关键字

auto

break

case

char

const

continue

default

do

double

else

enum

extern

float

for

goto

if

int

long

register

return

short

signed

sizeof

static

struct

switch

typedef

union

unsigned

void

volatile

while

 

1.2  ANSI C++标准补充的关键字

bool

catch

class

const_cast

delete

dynamic_cast

explicit

false

friend

inline

mutable

namespace

new

operatoer

private

protected

public

reinterpret_cast

static_cast

template

this

throw

true

try

typeid

typename

using

virtual

wchar_t


2.标识符

标识符是用户为程序中各种命名的元素所起的名字,这些元素包括:变量、符号常量、函数、函数参数、结构、类、对象等。

注意:

标识符要以字母或下划线开头,由字母、数字、下划线组成。

标识符不能与关键字相同。

标识符中的字母区分大小写。

标识符长度不宜超过32个字符。

3.字符常量

常量是指在程序中固定不变的值,常量可分为符号常量和字面常量两种。字面常量分为整型、浮点型、字符型和字符串型四种。

4.运算符

运算符用于对程序中的数据进行操作。(将在后面一章中介绍)

5.标点符号

标点符号在程序中起分割内容和界定范围作用。

1.3  C++标点符号

标点符号

描  述

标点符号

描  述

(空格)

语句中各成分之间的分割符

{(左花括号)

复合语句的开始标记符

;(分号)

语句的结束符

}(右花括号)

复合语句的结束标记符

'(单引号)

字符常量的起止标记符

//(双斜杠)

行注释的开始标记符

"(双引号)

字符串常量的起止标记符

/*(斜杠和星号)

块注释的开始标记符

#(井号)

预处理命令的开始标记符

*/(星号和斜杠)

块注释的结束标记符

 

 

1.3  编写C++程序

//这是一个简单的C++程序

#include<iostream>

using namespace std;

int main( )

{

cout<<"这是程序输出的信息"<<endl;

return 0;

}

注意:

C++所有函数名后都需要直接跟一对小括号,小括号内可以带参数也可以没有参数,小括号后直接跟用花括号括起的函数体。main( )称为主函数,无论主函数处于程序中的什么位置都被先执行,它是C++程序开始执行的入口。每个C++程序都必须有且只能有一个主函数。

#include是一个文件包括的预处理命令,每个以“#”开头的行都是预处理命令,并且一个预处理命令需要独占一行。iostream是一个定义了输入输出流对象的标准头文件。

C++标准程序库中的所有标识符都被定义于一个名为std命名空间(namespace,为了在程序中使用系统预先定义的标识符需要在程序前面引用std命名空间。命名空间是C++为了避免命名冲突引入的标识符管理方式。

如果没有using namespace std;语句,则程序中需要为每个预先定义标识指定范围(如std::cout)。也可以将iostream改成iostream.h,此时不能再使用using语句,但不主张这种用法。

C++可以采用行注释和块注释两种方式,行注释以双斜杠“//”开始到本行结束,块注释以斜杠星号“/*”开始到星号斜杠“/*”结束,块注释可以跨越多行。注释内容不被编译执行。

每条语句都需要以分号结束。可以在一行中书写多条语句,也可以将一条语句在连续的几行中书写完。

return 0;用于返回整数0给操作系统,以表示程序正常结束。

 

以上程序编写后保存成以CPP为扩展名的文件,该文件称为C++源程序文件。开发一个C++程序的过程通常包括编辑、编译、链接、运行和调试等步骤。

编辑C++源程序可以使用任何一个文本编辑器完成。

编译是将源程序文件转换成目标文件的过程。每个以.cpp为扩展名的源程序文件都需要编译成以.obj为扩展名的目标文件。

链接是将编译产生的一个或多个目标文件与程序中用到的库文件链接起来,形成一个可以在操作系统中直接运行的可执行程序文件(文件扩展名为.exe)。

运行是执行链接好的可执行程序,如果运行时发现错误需要时行调试。

 

1.4  数据类型

C++的数据类型可以分为基本类型、导出类型和用户定义类型三类。基本类型是由C++语言预先定义好的数据类型,包括:逻辑型、字符型、整型、浮点型和空值型。导出类型是由某种已知类型构造出来的数据类型,包括:数组、指针和引用。用户定义类型是指由用户给出具体定义后才能使用的数据类型,包括:枚举类型和类类型。

基本类型在程序中可以采用常量和变量两种。常量是指在程序执行过程中值不能改变的量,常量有字面常量和符号常量两种形式,字面常量的字面本身就是它的值,例如10-23.5'A'"Yongsai"等。

变量是程序中用于存储信息的单元,它对应于某个内存空间。定义变量时需要说明变量的名字和数据类型,变量名代表其存储空间,在程序中通过变量名存取其存储空间的值。

变量的声明格式:

[存储类别] 类型名 变量名[=初值表达式],...;

注意:

类型类别有autoregisterstaticextern四种,默认的存储类型为auto

变量名是一个标识符,需要遵守标识符命名规则。在程序中变量必须先定义后使用,在C++中变量只要在使用前定义即可,定义的位置不受限制。

如果同时定义多个变量,变量之间必须用逗号分开。

定义变量时可以给变量赋初值(初始化),否则变量的值不确定。

 

符号常量声明语句:

const 类型名 符号常量名=初值表达式,...;

注意:

符号常量名是一个标识符,需要遵守标识符命名规则。符号常量需要先声明后使用,声明的位置也不受限制。

必须在声明符号常量的同时为其赋初值。

如果同时声明多个符号常量,需要在符号常量之间用逗号分隔开。

如果类型名是int,则可以省略。

关键字truefalse是系统预先定义的两个符号常量,其值分别是10

 

1、逻辑型

逻辑型用关键字bool表示,也称bool型(布尔型),内存中占一个字节。逻辑型的值只包含truefalse,其中true对应整数1,表示逻辑真;false对应整数0,表示逻辑假。

 

2、字符型

逻辑型用关键字char表示,内存中占一个字节。可以将字符型看做是单字节整数,包括[signed] charunsigned char两种类型。

字符常量是用一对单引号括起来的一个字符,每个字符常量只能表示一个字符。在单引号中也可以是以一个反斜杠开始的转义字符,反斜杠后跟的字符将失去原来的含义,转义为具有某种控制功能的字符。反斜杠后可以跟一个特定的字母或跟一个具有13位的八进制整数或跟一个以字母x作为开始标记的具有12位的十六进制整数。其中八进制整数或十六进制整数就是对应字符的ASCII码。

常用的转义字符有:

\\   (反斜杠) \'    (单引号) \"    (双引号)

\n   (换行) \t    (水平制表) \b    (退格)

当在表达式中字符参与整数运算时将使用它的ASCII码值,常用字符的ASCII码值是'A'65'a'97'0'48

字符串常量是用一对双引号括起来的若干个字符。每个字符串常量末尾都默认有一个字符串结束符'\0',遇到'\0'是字符串结束的充分必要条件。

 

3.整型

整型用关键字int表示,与类型修饰符结合可以派生出以下类型:

[signed] int 4个字节(32位系统)

unsigned [int] 4个字节(32位系统)

[signed] short [int] 2个字节

unsigned short [int] 2个字节

[signed] long [int] 4个字节

unsigned long [int] 4个字节

整型常量在C++中可以用十进制、八进制和十六进制表示。十进制整数由首位非0的一串十进制数字组成;八进制整数以数字0开头后面接若干个八进制数字;十六进制整数以数字0和字母x(或X)开头后面接若干个十六进制数字。

注意:在八进制整数中不能含有数字89

可以在任意整数后加字母u(或U)表示这是一个无符号整数,在整数后加字母l(或L)表示这是一个长整数。字母ul可以同时使用,并且没有顺序要求。

 

4.浮点型

浮点型包括单精度型和双精度型两种,单精度型用关键字float表示(占4个字节),双精度型用关键字double表示(占8个字节)。

实型常量可以采用小数形式和指数形式表示。注意:采用小数形式表示(或称定点表示)时小数点的某一侧可以没有数字;采用指数形式表示(或称浮点表示)时字母e(或E)的两侧都必须有数字,并且后面只能是一个整数。浮点表示时E前面的部分称为尾数,E后面的部分称为指针(即10的指数幂)。

对于一个实型常量C++自动按一个双精度数来存储,若在实型常量后面加字母f(或F)则按单精度数来存储。

当采用浮点表示时,如果尾数中的小数点前面有且仅有一位非0数字,则称为标准化浮点数。

单精度型有效位不超这7位,双精度型有效位不超过15位。

 

5.空值型

空值型用关键字void表示。空值型的取值为“空”,C++中不存在void型常量和变量。void可以用于声明一个指针变量,或用于指定函数返回值类型(此时函数无返回值)。

 

6.枚举型

枚举型用关键字enum表示。枚举类型属于用户定义类型,需要先声明枚举类型才能使用,声明格式如下:

enum [枚举类型名]{枚举值列表};

注意:

枚举值列表是用逗号隔开的若干个枚举值,每个枚举值都是一个枚举常量。枚举常量是一个标识符,在程序中枚举常量可以直接使用。

在声明枚举类型时,可以给枚举值赋整型常量。如果没有赋值则第1个对应于整数0,往后依次加1;如果给某个枚举值赋值,则从这个枚举值开始往后按所赋的值依次加1

声明枚举类型后可以定义该类型的变量,定义变量时关键字enum可以省略。

 

7.变量的属性

1)全局变量和局部变量

全局变量是在所有函数定义、类定义和复合语句之外声明的变量。全局变量从定义的位置开始到文件末尾有效,若定义时未赋初值则系统会自动为其赋0

局部变量是在某个函数定义、类定义或复合语句内声明的变量。局部变量只能在声明它的函数、类或复合语句内有效。

2)生存期和作用域

生存期是指从一个变量被声明且分配了内存开始,直到该变量失效,占用的内存空间被释放为止。变量的生存周期有以下两种:

其一、变量由编译程序在编译时给其分配存储空间(称为静态存储分配),并在程序执行过程中始终存在。

其二、变量由程序在运行时自动给其分配存储空间(称为自动存储分配)。它们在程序执行到所在函数(或块)时被创建,在函数(或块)执行结束时释放所占空间。

全局变量属于静态存储分配,局部变量属于自动存储分配。

作用域是指变量名可以代表该变量存储空间的范围。变量的作用域小于或等于其生存期。当两个同名的变量作用域重合时,在作用域重合处有效的是最新声明的变量。为了在重合处使用同名的全局变量,可以在变量名前使用作用域运算符,例如::a”。

3)变量的存储类别

auto变量(自动变量):声明局部变量时默认的存储类别为autoauto变量所占用存储空间的分配和释放工作由系统自动完成。

register变量(寄存器变量):用register声明局部变量时,该变量可能用寄存器作为其存储空间(当寄存器不够用时按自动变量处理)。

static变量(静态变量):任何静态变量的生存期将延续到整个程序结束(即只有到程序结束时才释放所占存储空间)。静态变量在编译时就进行初始化操作,在分析程序时对于静态局部变量可以这样认为只有第一次遇到声明其的语句时执行初始化操作,以后再次遇到时不再执行初始化操作。

extern变量(外部变量):外部变量一般用于多个文件组成的程序中。

 

8.typedef类型说明

可以使用关键字typedef为已有类型名定义一个新类型名,格式如下:

typedef  已有类型名  新类型名;

注意:typedef类型说明并没有真正地定义新的数据类型。

 

1.5  运算符和表达式

C++语言提供了丰富的运算符(或称操作符),运算符不仅具有优先级,还具有结合性。

1.4  C++运算符的优先级与结合性

优先级

运算符

描    述

用    法

结合性

1

::

全局域

::name

左结合

::

类域

classname::member

2

.

通过对象的成员访问

object.member

左结合

->

通过指针的成员访问

pointer->member

[ ]

下标

pointer[expr]

( )

函数调用

function(expr_list)

( )

类型构造

type(expr_list)

++

后缀增量

lvalue++

右结合

--

后缀减量

lvalue--

3

sizeof

数据长度

sizeof expr

右结合

sizeof

类型长度

sizeof(type)

++

前缀增量

++lvalue

--

前缀减量

--lvalue

~

按位取反

~expr

!

逻辑非

!expr

-

取负

-expr

+

取正

+expr

&

取地址

&expr

*

值引用

*expr

new

动态分配

new type

delete

释放变量

delete pointer

delete

释放数组

delete [ ] pointer

( )

强制类型转换

(type)expr

4

.*

在对象上通过指向成员的指针访问成员

object.*pointer_to_member

左结合

->*

在指针上通过指向成员的指针访问成员

pointer->*pointer_to_member

5

*

expr*expr

左结合

/

expr/expr

%

取余(取模)

expr%expr

6

+

expr+expr

左结合

-

expr-expr

7

<<

按位左移

expr<<expr

左结合

>>

按位右移

expr>>expr

8

<

小于

expr<expr

左结合

<=

小于等于

expr<=expr

>

大于

expr>expr

>=

大于等于

expr>=expr

9

==

等于

expr= =expr

左结合

!=

不等于

expr!=expr

10

&

按位与

expr&expr

左结合

11

^

按位异或

expr^expr

左结合

12

|

按位或

expr|expr

左结合

13

&&

逻辑与

expr&&expr

左结合

14

||

逻辑或

expr&&expr

左结合

15

? :

条件表达式

expr?expr:expr

右结合

16

=

赋值

lvalue=expr

右结合

*=

乘并赋值

lvalue*=expr

/=

除并赋值

lvalue/=expr

%=

取余并赋值

lvalue%=expr

+=

加并赋值

lvalue+=expr

-=

减并赋值

lvalue-=expr

<<=

按位左移并赋值

lvalue<<=expr

>>=

按位右移并赋值

lvalue>>=expr

&=

按位与并赋值

lvalue&=expr

|=

按位或并赋值

lvalue|=expr

^=

按位异或并赋值

lvalue^=expr

17

,

逗号

expr, expr

左结合

由一个或多个运算符与操作符连接而成的有效运算式称为表达式,任何表达式都有一个运算结果。进行表达式运算时从表达式左向右扫描,如果一个操作数连接两个运算符则按运算优先级计算,如果优先级相同则按结合方向计算。

1.赋值运算

格式:  变量=表达式

注意:

赋值运算符左边必须是一个lvaluelvalue 通常指的是可以寻址并且可以对该地址内容存储的对象进行写操作,变量一般就是一个lvalue)。

每个赋值表达式都有一个值,这个值就是左端变量得到的值。

在赋值前系统会自动把右边表达式的值转换为与左边变量类型相同的值,然后再赋值。如果是实数转换成整数,则直接截取其整数部分。

复合赋值运算符的运算方式是将右边表达式的值同左边变量的值进行相应的运算后,再把运算结果赋给左边的变量。

一个赋值表达式本身也是一个lvalue

 

2.算术运算

算术运算是指int型(包括char型)、float型、double型的数值类数据计算后得到同一类型数据的运算。运算符包括:+-*/%

注意:

算术表达式的值的类型与参加运算的数据的“高级”类型一致。需要特别注意的是两个整数相除得到的值也为整数,为了得到一个带小数的值需要至少将其中一个操作数转换为实型。

取余运算符%”要求参与运算的操作数均为整数(包括char型)。余数的符号与被除数符号一致。

 

3.增量、减量运算

包括前缀增量、后缀增量和前缀减量、后缀减量四种表达式,格式:

lvalue++

++lvalue

lvalue--

--lvalue

前缀增量(减量)和后缀增量(减量)的区别是:当增量(减量)表达式要参与其他运算时,前缀表达式是先令lvalue1(减1)然后再参加其他运算;后缀表达式是先令lvalue参加其他运算然后再令lvalue1

 

4.关系运算

关系运算符包括:< <= > >= == !=

关系运算表达式运算结果为truefalse(分别对应整数10)。需要特别注意等于运算符==”与赋值运算符“=”的区别。

 

5.逻辑运算

逻辑运算符包括:! && ||

逻辑运算表达式的运算结果为truefalse

注意:

C++中任何一个具有0或非0值的表达式都可以作为逻辑表达式使用。

运算符&&遇假则假,所以当&&左边表达式为“假”时不再进行右边表达式的计算;运算符||遇真则真,所以当||左边表达式为“真”时不再进行右边表达式的计算。

 

6.位运算

位运算符包括:& | ^ ~ << >>

需要注意的是进行位运算表达式的计算时,需要将参与运算的操作数转换成对应的二进制数,然后将两个二进制数的对应二进制位进行相应的操作。并且要注参与位运算的操作数均为整数。

1)按位与“&”运算的运算规则是对应二进制位只要有一个为0,则该二进制位与运算后结果为0

2)按位或“|”运算的运算规则是对应二进制位只要有一个为1,则该二进制位或运算后结果为1

3)按位异或“^”运算的运算规则是对应二进制位如果都为1或都为0,则该二进制位异或运算结果为0;如果一个为1另一个为0,则异或运算结果为1

4)按位取反“~”运算是一个单目运算符,运算规则是如果二进制位为1则取反结果为0,如果二进制位为0则取反结果为1

5)按位左移“<<”运算的运算规则是在二进制数右边补充n(右边操作数)个0

6)按位右移“>>”运算的运算规则是将二进制数右边的n(右边操作数)个二进制位去掉。

注意:按位左移和按位右移的运算规则只针对操作数不太大的情况(等级考试时数值都不会太大)。

 

7.其他运算

1)条件运算

条件运算符? :”是C++中唯一的三目运算符,格式:

表达式1?表达式2:表达式3

首先计算表达式1,如果表达式1为“真”则计算出表达式2的值作为整个条件表达式的值;如果表达式1为“假”则计算出表达式3的值作为整个条件表达式的值。

2)逗号运算

逗号运算符可用于指明对多个表达式从左至右进行顺序求值,所以逗号表达式也称为顺序求值表达式。格式:

表达式1,表达式2,...,表达式n

最后一个表达式n的值为整个逗号表达式的值。

3sizeof运算

sizeof运算符可用于进行字长(即占用字节数)的提取操作,返回的值是一个整数,格式:

sizeof(类型名)

sizeof 表达式

4)强制类型转换

格式: (类型名) 表达式

功能是将表达式的值转换成“类型名”所指定类型的值。需要注意的是原表达式或变量的类型并不会因此而改变。

5)类型构造

格式: 类型名(表达式)

功能是使用表达式的值来构造一个具有指定类型的值。需要注意的是原表达式或变量的类型并不会因此而改变。

注意:强制类型转换与类型构造在功能上等价,如果类型名用小括号括起则为强制类型转换否则为类型构造。

 

 


2章 C++语句

C++提供的基本控制结构包括以下3种类型:

1)顺序结构:按照语句出现的顺序从上而下、从左向右依次执行。

2)选择结构:按照给定条件选择执行程序中的语句。

3)循环结构:按照给定条件重复执行程序中的语句。

语句是C++程序中的基本功能单元,用于完成某相操作,每条语句都必须用一个分号“;”作为结束标志。根据功能的不同可以分为6种类型的语句:

1)声明语句:用于对程序中的各种标识符进行声明、定义、初始化。

2)表达式语句:用于对程序中的数据进行具体操作。

3)选择语句:用于实现程序的选择结构。

4)循环语句:用于实现程序的循环结构。

5)跳转语句:用于实现程序执行流程的转移。

6)复合语句:用于表示程序的语句块。

 

2.1  顺序结构

1.声明语句

声明语句也称说明语句,在C++程序中一个名称在使用之前先被声明。一般声明语句也具有定义功能,所谓定义是指对某个名称所指代的实体进行具体描述。C++规定,一个名称的定义只能出现一次,而其声明却可以出现多次,同一个名称的多个声明必须在类型上保持一致。注意,在C++中声明语句可以出现在任何其他语句能够出现的地方。

声明语句可以进行如下操作:

1)变量声明

2)符号常量声明

3)函数声明

4)类型声明

 

2.表达式语句

在任何合法的C++表达式后面添加一个分号便构成了一个表达式语句,用于对数据的操作和处理工作。一般包括赋值操作、函数调用操作和输入输出操作。

 

3.复合语句和空语句

复合语句也称块语句,它是用一对花括号{ }”将若干条语句括起来而组成的一条语句。不论花括号中有多少条语句,在语法上一个复合语句被视为一条语句。

空语句是由一个单独的分号组成。执行空语句时不产生任何操作,但有时空语句会改变程序执行流程从而影响程序的运行结果。

 

4.基本输入输出

C++程序的输入输出操作是通过标准库中的输入输出流对象来完成的。在标准头文件iostream中定义了代表屏幕的标准输出流对象cout和代表键盘的标准输入流对象cin

在程序中为了使用cincout等输入输出的相关对象,需要在程序中使用以下预处理命令:

#include<iostream>

还应使用引用语句:using namespace std; 否则在程序中每个与输出输出相关的对象名前都需要加上作用域std::”。

使用cout进行数据输出操作的一般格式为:

cout<<表达式;

其中<<”称为插入运算符。语句的功能是将表达式的值输出到屏幕当前光标所在位置。C++允许在一个cout中连续使用几个插入运算符来多项数据。

为了在输出时换行,可以使用换行符'\n'或预定义标识符endl

 

使用cin进行数据输入操作的一般格式为:

cin>>lvalue;

其中>>”称为提取运算符。语句的功能是程序暂时中止执行,待待用户从键盘上输入一个数据。如果用户键入一个有效的数据并按下回车键,程序将此数据保存到lvalue中并继续执行后续语句。

C++允许在一个cin中连续使用几个提取运算符来输入多项数据,需要特别注意,在连续输入多项数据时,应使用空白字符(包括空格、回车、制表位)将两项数据分隔开。对于char型,两个字符之间空白字符可有可无;对于bool型,输入时需要输入10表示“真”或“假”,而不是输入truefalse

 

2.2  选择结构

1.if语句

if语句又称条件语句,其格式如下:

if (条件表达式)

    语句1

else

    语句2

执行过程:首先计算条件表达式,如果条件表达式的值为非0(即“真”)则执行if控制的语句1,然后执行if...else...后的下一条语句(此时不执行语句2);如果条件表达式的值为0(即“假”)则执行else控制的语句2,然后执行if...else...后的下一条语句(此时不执行语句1)。

注意:

if后的条件表达式必须用小括号括起。

ifelse分别控制且只能控制紧跟其后的一条语句(分别称为if子句和else子句)。如果需要控制“多条”语句,必须用花括号将这些语句括起组成一条复合语句。

else子句可以省略,此时,如果条件表达式为0则跳过if语句执行其后的下一条语句。

条件表达式可以是任何合法的有0或非0值的表达式。条件表达式也可以用于定义变量,此时,最好给变量同时初始化,表达式的值与初值一致,如果同时定义多个变量则与第一个变量的初值一致。在条件表达式定义的变量只能在if...else...语句中有效。

一个if...else...语句在语法上视为一条语句。

 

if子句或else子句如果也是一条if...else...语句,则称为if语句的嵌套。例如:

if (条件表达式)

    if (条件表达式)

        语句1

    else

        语句2

else

    if (条件表达式)

        语句3

    else

        语句4

if...else...的嵌套中,ifelse的配对关系是:else总是与在它前面最近的末配对的且可见的if配对,而不是以缩进为依据的。复合语句内的if(或else)是不能与复合语句外的else(或if)配对的。

 

2.switch语句

switch语句也称为开关语句,其功能是根据给定表达式的值决定从那个语句序列开始执行,格式如下:

switch(表达式){

case 常量表达式1:语句系列1

case 常量表达式2:语句系列2

....

default:语句系列n+1

}

执行过程:首先计算出switch后小括号内表达式的值,然后程序跳转到与该值相等的常量表达式所在的case标号往后执行;如果没有相等的常量表达式并且有default标号,则程序跳转到default标号往后执行。程序一旦跳转到某个标号,则会从该标号开始往后执行各语句系列中的语句直到switch语句体结束,除非遇到break语句才提前结束switch语句的执行。

注意:

switch后的表达式需要用小括号括起,并且该表达式的值必须是一个整型值(包括char型和enum型)。表达式可以用于定义整型变量,此时,最好给变量同时初始化,表达式的值与初值一致,如果同时定义多个变量则与第一个变量的初值一致。在表达式定义的变量只能在switch语句中有效。

case后常量表达式必须是一个整型值(包括char型和enum型),并且不能含有变量。

case后常量表达式的值不能相同。

case标号的数量不限制,default标号最多只能有一个,它们的出现顺序不限制(但不同的出现顺序可能执行结果不一样)。

各标号后语句系列中语句的数量不限制,也不需要用花括号将语句系列中的多条语句括起。

switch语句可以嵌套,此时,casedefault只对包含它的switch有效。

 

2.3  循环结构

1.for语句

for语句格式:

for(表达式1;表达式2;表达式3)

    循环体

执行过程:首先计算表达式1,然后计算表达式2,如果表达式2为非0(即“真”)则接着执行循环体中的语句,执行完循环体中的语句后执行表达式3,然后再次执行表达式2继续执行循环判断;如果表达式20(即“假”)则结束循环的执行往后执行它的下一条语句。

注意:

for只能控制且必须控制紧跟其后的一条语句作为循环体,如果需要控制“多条”语句则需要用花括号将这些语句括起组成一条复合语句。

表达式1可以用于定义变量,此时,需要给变量同时初始化(否则变量的值为随机数)并且此时表达式1不能是一个逗号表达式。在表达式1中定义的变量可以从for所在的位置开始到for所在语句块结束为止有效。

表达式1、表达式2、表达式3可以是任何合法的C++表达式,并且它们可以任意省略,但用于分隔表达式的两个分号不能省略。如果省略表达式2,则认为循环条件永远为“真”。

 

2.while语句

while语句格式为:

while(条件表达式)

    循环体

执行过程:首先计算条件表达式,如果条件表达式的值为非0(即“真”)则执行循环体,执行完循环体中的语句后重新回到条件表达式继续判断;如果条件表达式的值为0(即“假”)则结束循环去执行其后的下一条语句。

注意:

while只能控制且必须控制紧跟其后的一条语句作为循环体,如果需要控制“多条”语句则需要用花括号将这些语句括起组成一条复合语句。

条件表达式可以用于定义变量,此时,最好给变量同时初始化,表达式的值与初值一致,如果同时定义多个变量则与第一个变量的初值一致。在条件表达式定义的变量只能在while语句中有效。

 

3.do...while语句

do...while语句的格式如下:

do

    循环体

while(条件表达式);

执行过程:首先执行循环体,执行完循环体中的语句后计算条件表达式,如果条件表达式的值为非0(即“真”)则重新回去执行循环体;如果条件表达式的值为0(即“假”)则结束循环去其后的下一条语句。

注意:

do...while只能控制且必须控制一条语句作为循环体,如果需要控制“多条”语句则需要用花括号将这些语句括起组成一条复合语句。

do...while循环的循环体致少执行一次,而for循环和while循环没有此特点。

条件表达式不可以用于定义变量。

 

各种循环可以相互嵌套,所谓循环嵌套是指在一个循环体内又包含另一个循环结构。

 

4.跳转语句

C++共有4种无条件跳转语句,它们是:break语句、continue语句、return语句和goto语句。

1break语句

break语句的功能是跳出直接包含它的switch语句或循环语句,即结束其所在switch语句或循环语句去执行下一条语句。注意,它只能跳出直接包含它的一层switch语句或循环语句。

2continue语句

continue语句的功能是立即转到循环条件所在处继续进行循环条件的判断,对于for循环要先执行其表达式3再进行循环条件的判断。

注意:break语句只对switch语句或循环语句有效,而continue语句只对循环语句有效。

3return语句

return语句的格式如下:

return 表达式;

return;

语句的功能是结束其所在函数体的执行返回到调用该函数的位置,如果return后有表达式则将表达式的值作为函数值返回。对于一个返回类型不为void的函数,其函数体中至有一条return语句,并且return后需要有表达式。对于一个返回类型为void的函数,函数体中的return语句后不能有表达式。

 

 

 

 


3章 导出类型

3.1  数组

数组(Array)是由固定数目元素组成的数据结构,同一数组的所有元素的类型都相同。数据元素是通过下标进行访问的。数据可以是一维的,也可以是多维的。

1.一维数组

一维数组是由具有一个下标的数组元素组成的数组,定义格式如下:

类型名  数组名[数组长度];

注意:

定义一维数组时,数组名后必须用一个中括号将数组长度括起。

定义数组时,中括号中的数组长度不能含有变量,即必须是一个正的常量整型表达式。该常量的值指定了数组中的元素个数。

一维数组元素在内存中是连续存放的。

 

定义数组的同时可以进行初始化,此时,必须将元素的初值按顺序放在一对花括号中,初值之间用一个逗号分隔。

注意:

初值个数不能大于数组长度;如果初值个数小于数组长度,则没有对应初值的元素自动赋0

如果定义数组同时初始化,则可以省略数组长度,此时,数组长度等于初值个数。如果没有同时初始化,则必须给出数组长度。

只能在定义的时候可以给多个元素同时初始化。

 

数组也需要先声明后使用,访问一维数组元素的格式如下:

数组名[下标]

注意:对于数组长度为N的数组,其下标的范围是0~N-1,即数组第一个元素的下标为0,最后一个元素下标为N-1。如果下标不在此范围,则程序运行时可能会出现严重错误,但编译时不会发现。下标表达式可以含有变量。

 

对数组元素的排序和查找。

 

2.多维数组

二维数组是由具有两个下标的数组元素组成的数组(其中第一个下标为行标、第二个下标为列标);三维数组是指带有三个下标的数组,依此类推。

二维数组的定义格式如下:

类型名 数组名[行数][列数];

注意:

定义二维数组时,数组名后必须用两个中括号分别将数组的行数和列数括起。

定义数组时,中括号中不能含有变量,即必须是一个正的常量整型表达式。行数乘以列数就是二维数组元素个数。

二维数组元素在内存中是按行连续存放的。

 

二维数组在定义时也可以初始化,可以将所有初始放在一对花括号中对数组初始化,此时,将按数组元素在内存中的存放顺序依序对应赋值;也可以用花括号将各行元素的初值分别括起,各花括号之间用一个逗号分隔。

注意:

初值个数不能多于元素个数,按行方式初始化时各花括号中初值个数不能多于列数。如果初值个数少于元素个数,则没有对应初值的元素自动赋0

如果在定义时同时初始化,可以省略第一维的长度(即省略行数),此时,系统将根据初值个数确定数组的行数。

 

访问二维数组元素的格式如下:

数组名[行标][列标]

行标和列标都是从0开始,访问数组元素时下标可以含有变量。

 

按行、按列遍历二维数组。

 

注意:多维数组作为函数的形参时可以省略数组中第一维的长度,其它维的长度必须给出并且要与实参对应维的长度一致。多维数组只可以作为引用参数传递给函数,函数不能返回一个数组类型的值。

 

3.字符数组

字符数组的所有元素都是char型。在C++中用空字符('\0')来作为一个字符串结束的标志,如果用字符数组来存放一个字符串,则字符数组中在存放有效字符的元素后面必须紧跟着存放一个空字符。否则,该数组中的字符不构成一个字符串。

在定义字符数组的同时,可以采用字符串常量的形式给字符数组初始化,也可以将字符串拆成单个字符并连续的放在一对花括号中对字符数组初始化。

C++的标准库中定义了一个用户自定义的string类型,string类型不是C++语言本身的一部分而是由C++标准库来支持的。所以使用string类型之前,需要在程序中包含头文件string并引用其所在的std命令空间,如下所示:

#include<string>

using namespace std;

string定义的变量既可用赋值表达式给其赋值,也可以对其像数组一样使用(即可以对其进行下标运算)。

 

在头文件cstring中提供了很多字符串操作函数,常用的字符串处理函数如下:

1strcpy()函数

函数声明如下:

char * strcpy(char *s1, char *s2);

功能是将s2中的字符串拷贝到s1中。注意,在程序中不能将一个字符串或字符数组赋值给一个字符数组,应通过strcpy函数实现。

2strcat()函数

函数声明如下:

char * strcat(char *s1, char *s2);

功能是将s2中的字符串连接到s1的字符串末尾中。

3strcmp()函数

函数声明如下:

char * strcmp(char *s1, char *s2);

功能是比较s1s2中字符串的大小,如果相等则返回0,如果s1的字符串大于s2的字符串则返回1,如果s1的字符串小于s2的字符串则返回-1

4strlen()函数

函数声明如下:

int strlen(char *s);

功能是返回s中字符串的有效字符个数(不包括结束符)。

5strstr()函数

函数声明如下:

char * strstr(char *s1, char *s2);

功能是在s1字符串中查找s2字符串的首次出现位置。如果找到则返回首次出现的指针,否则返回NULL

 

3.2  指针

指针是一个特定类型数据的存储地址,指针变量的声明格式为:

类型名 *指针变量名;

类型名也称为基类型,它用于确定指针变量所指对象的类型。

与指针有关的两个运算符:&——称为取址运算,即返回其操作数的内存地址(指针);*——称为值引用运算,即返回其操作数所指对象的值,要求其操作数为一个指针。

若有定义:

int x=100;

int *p;

当:

p=&x;

则称指针p指向了对象x*p则为p所指对象x,即*p可以代替x

注意:指针变量必须先赋值才能引用,即需要先给指针变量赋一个确定的存储单元地址才能对其进行值引用运算。可以采用以下方式赋值:

其一、使用new运算符(或malloccalloc等函数)给指针分配一个具体的存储空间。

其二、将另一个同类型的指针赋值给它。

其三、对某个对象进行&运算后赋值给它。

 

指针可以进行的运算有:

指针与整型量进行加减运算

一个指针加1得到一个指向下一个存储空间的指针,一个指针减1得到一个指向前一个存储空间的指针。由于数组元素在内存中是连续存放的,所以当指针指向下标为i的数组元素时,对指针加n得到的是一个指向下标为i+n的指针,对指针减n得到的是一个指向下标为i-n的指针。

若两个指针基类型相同,则它们可以相互赋值,此时,它们指向同一对象。

如果两个指针指向同一存储空间,当其中一个指针所向空间被释放时,另一个指针所指存储空间也被释放,这称为指针的悬挂问题。这时,如果对这另一指针进行操作可能会出错。

若两个指针指向同一数组中的元素则可以进行关系运算,其中指向前面元素的指针小于指向后面元素的指针。

若两个指针指向同一数组中的元素,则它们可以相减,结果为两个指针之间的元素个数。

 

C++中数组的名字就是指向该数组第一个元素(下标为0)的指针(即数组的首地址),它是一个常量,所以指针和数组通常可以互换。

下标运算等价于指针运算,例如,a[i]等价于*(a+i)

对于字符串常量,可以看成是一个无名的字符数组,字符串常量本身就是一个指向这个无名字符数组的第一个字符的指针。

 

3.3  引用

引用就是某一对象如变量)的一个别名,对引用的操作与对对象直接操作完全一样。引用的声明格式

类型 &引用名=对象名;

注意:

声明语句中在类型名后跟的&”不是取地址运算,而只是起到标识现定义的是一个引用,以后使用引用名时不再需要“&”。引用的类型必须与它所代表对象的类型一致

声明引用名时必须同时用一个对象名对其初始化,以指定该引用所代表的对象,并且无法在声明之后再改变引用所代表的对象。与指针不同,不能有NULL引用。

对引用的任何操作实际上就是对它所代表对象的操作。

系统不会为引用名分配存储空间。

不能创建引用数组,也不能给数组指定引用;

引用的一个重要用途是作为函数的参数,使用引用传递函数的参数(此时对应实参不参是常量),在内存中并没有产生实参的副本,它是直接对实参操作。即在被调函数中对引用的操作实际上就是对主调函数对应实参的操作。

 

3.4  动态存储分配

内存分配可以分为静态存储分配和动态存储分配两种,所谓静态存储分配是指系统在编译时就为对象分配存储空间(例如变量、数组),静态存储分配在栈内存中进行;所谓动态存储分配是指系统在运行时根据要求分配存储空间,动态存储分配在堆内存中进行。C++中动态存储分配是通过newdelete运算符来实现的。

1.new运算

new运算符用于申请动态存储空间,有如下两种格式:

指针=new 类型;

指针=new 类型[长度];

new运算返回一个指向所分配存储空间首地址的指针,该指针的基类型就是new后的类型,如果分配失败(即堆内存已耗尽)则返回NULL。其中,第一个格式用于分配一个存储单元(如变量),第二个格式用于分配连续的多个存储单元(如数组)。

注意:

第一个格式可以同时初始化,此时,需要将初值表达式用小括号括起后紧跟在类型名后。第二个格式不能同时初始化。

第二个格式的“长度”就是所分配的存储单元个数(如元素个数),长度表达式可以含有变量。

 

2.delete运算

程序中动态分配的内存空间在确定不再使用时应将其释放,以便系统重新分配。在C++程序中由new分配的动态内存空间必须通过delete运算释放。有如下两个格式:

delete 指针;

delete [ ] 指针;

第一个格式用于释放由new 类型”分配的内存,第二个格式用于释放由“new 类型[长度]”分配的内存。

 

 


4章 函数

函数是一个可以独立完成某个功能的语句块,一个C++程序可以由一个或多个函数组成,程序从主函数main开始执行。函数可以分为标准函数(或称预定义函数)和用户自定义函数,标准函数是系统已实现并通过函数训形式提供的函数,如sqrt()strcpy()等。如果程序中要使用某个标准函数,必须使用include预处理命令将相应的头文件包含到程序中。

 

4.1  函数定义

由于标准函数不可能提供完所需的功能,所以需要用户根据需要自定义函数。函数的定义形式如下:

返回类型 函数名(形参列表)

{

    函数体

}

说明:

返回类型又称函数类型,用于指定函数返回值的类型,缺省的返回类型为int型。如果函数不需要返回值,则应将返回类型指定为void

当函数有返回值时(即返回类型不为void),应保证函数的每个可能执行路径上都有return语句返回值。

在函数中一旦执行return语句,函数将立即结束执行并返回到主调函数调用处往后继续执行。如果函数中没有return语句,则执行完最后一条语句后返回。

形参列表用于说明函数的各个形参,各形参之间用逗号分隔,每个形参都必须单独给出类型。形参列表可以为空,即函数可以没有形参(无参函数)。

定义函数时,不论函数是否带有形参函数名后都需要跟一对小括号。

定义函数时,需要用一对花括号将函数体的语句括起(即使没有语句花括号也不能省略)

不能嵌套定义函数,即不能在一个函数体内定义另一个函数。

 

在程序中各函数的定义位置没有限制,但是如果函数的调用出现在函数定义之前则编译时会出现“函数未定义”的错误,为了解决这个问题可以将函数的定义放在前面,或在调用前对函数进行声明。对函数的声明称为函数原形,函数原形给出了函数名、返回类型以及在调用函数时必须提供的参数个数和类型。函数原型的格式为:

返回类型 函数名(形参列表);

注意:函数原型要保持与函数定义的首部一一对应,其中形参中的参数名可以省略。

 

4.2  函数参数

函数参数可以分为形式参数和实在参数两种,形式参数是指在进行函数定义时函数名后小括号内的参数,实在参数是指在进行函数调用时函数名后小括号内的参数。C++函数参数传递有值传递、地址传递和引用传递三种。

1.值传递

值传递是将实参值的副本传递(拷贝)给被调函数的形参,此时形参和实参分别使用不同的存储单元,所以改变形参的值对实参的值无任何影响。

值传递时形参是一般的变量,实参是一般的变量、常量或表达式。

 

2.地址传递

地址传递是将实参的地址传递给形参指针,即形参指向对应的实参。此时,通过对形参进行指针(或下标)运算可以操作相应的实参。

地址传递时形参是指针变量或数组,实参是数据的地址(如变量地址、数组名)。

 

3.引用传递

引用传递时将实参对象传递给引用参数,从而确定引用所代表的实参名。此时,在函数中操作引用实际上就是操作对应的实参。

引用传递时形参是引用,实参是变量名。

可以使用关键字const来修饰引用参数,此时,不能通过引用参数修改实参的值。

 

4.默认参数

C++中可以为形参指定默认值,在函数调用时没有指定与形参相对应的实参时就自动使用默认值。

注意:

默认参数必须在函数调用的前面出现的函数原型声明或函数定义中指定(一般在函数第一次出现时指定),否则无效。并且只能指定一次,否则出错。

默认参数必须在形参列表的后面,即如果某个形参指定了默认值则其后面的形参也必须指定默认值,否则出错。

 

4.3  函数调用

函数调用的格式如下:

函数名(实参列表)

注意:进行函数调用时,实参的个数、类型及顺序必须与函数定义时的形参一致。如果某个形参有默认值则可以不给出对应的实参。

函数调用可以作为单独的一条语句,也可以在表达式中或作为实参。如果函数的返回类型为void则不能在表达式中或作为实参。

在进行函数调用时系统会将实参传递给相应的形参,并转到被调函数执行,执行完被调函数后程序转回到主调函数的调用处继续执行。根据函数调用的特点可以将函数调用分为嵌套调用和递归调用两种。所谓嵌套调用是指在一个函数中调用另一个函数;所谓递归调用是指在函数内直接或间接调用它本身。

 

4.4  函数重载

函数重载是指用同一个函数名来定义功能上类似的多个函数,程序将根据函数的参数来判断应调用哪个函数。

注意:

重载函数至少要在参数个数或参数类型上有所不同,否则将出错。

如果函数只是返回类型不同而其它完全相同,则不能作为重载函数使用,此时会出现“函数被重复定义”的错误。

 

4.5   内联函数

在编译时将程序中出现的内联(inline)函数的调用用内联函数的函数体代表,就像宏函数展开一样,所以执行时它没有参数压栈和退栈操作,减少了调用开销,因此,内联函数比一般函数执行效率更高。

内联函数必须在进行函数定义时用inline指定(一般写在返回类型前),否则不起作用。在进行函数原型声明时inline可以省略。

注意:

在类的说明部分定义(实现)的任何函数不论是否有inline都为内联函数。

如果函数中代码太多、结构太复杂,编译器会放弃内联方式而以一般函数处理。

 

 


5章 类和对象

类是面向对象程序设计的核心,是通过抽象数据类型方法实现的一种用户自定义数据类型,它同时包含了数据和对数据进行操作的函数。类是某一类对象的抽象,而对象是某一种类的实例。

 

5.1  类的定义

    类的定义可以分为两部分:说明部分和实现部分。说明部分用于说明类中包含的数据成员和成员函数,实现部分用于对成员函数的定义。

 

 

5.2  对象的定义

5.3  构造函数和函数

5.4  自由存储对象

5.5  this指针

5.6  静态成员

5.7  常成员

5.8  友元

5.9  对象数组

5.10  成员对象


6章 继承和派生

6.1  继承与派生

6.2  派生类的构造函数和析构函数

6.3  多继承与虚基类

6.4  虚函数与多态性

 

 7章 运算符重载

7.1  运算符函数与运算符重载

7.2  典型运算符的重载

8章 模板

8.1  函数模板

8.2  类模板

9章 C++

9.1  流的概念

9.2  格式控制

9.3  文件流

 

 


评论