C++


认识C++的对象

1.1初识c++的函数和对象

      C++语言兼容C语言,这一语句在C++中则等效为声明一个整数对象。

      即只要换一下思维模式,就可以通过C语言的变量认识C++的对象。

      在C++中则称为结构对象。

      1.混合型语言

   C++程序以.CCP作为文件扩展名,并且必须有一个且只能有一个名为main(不是C++的关键字)的主函数。

    2灵活的注释方式

    C++除沿用C语言的从“、/*”开始,直到“*/”结束的注释方式之外,引入了更灵活的方式“//”,注释的有效范围从“//”至本行结束。

    3.使用输出和输入对象

    C++将数据从一个对象流向另一个对象为“流”。从流中获取的数据的操作称为提取操作。

   cincout都不是C++语言本身的定义的一部分,而是由C++的一套面向对象类体系提供支持并作为C++标准程序库的一员所以在使用它们之前需要在主函数前使用#include语句将其包含。C++标准备输入输入库的头文件时iostrean在程序中使用定义的方法。

4.使用命名空间

   所谓的命名空间(namespace)是一种将程序库名称封装起来的方法,它提高了程序的性能和可靠性。

   若要在程序中使用cincout这两个iosteam数的对象,不仅要包含iosteam头文件,还得让命名空间std内的名称曝光这一条语句就是让命名空间中的名称曝光。

   C++新标准就是将标准类库的头文件与一般的头文件要(需要使用扩展名“.h)区分开来。当然,也可以自己定义符合标准

   准库头文件,使用这种头文件时,也需要有同时使用命名空间语言。

5.对象的定义及初始化

   定义对象包括它命名并赋予它类据类型

6.函数原型及其返回值

   函数都需要有类型说明。int main()指出main是整数类型,返回值由return后面的表达式决定,且表达式的值必须与声明函数的类型一致。

返回“0”值来表示main函数结束。如果函数确定不需要返回值,还可以用void标识,一旦使用void标识,函数体内就再需要使用return语句。

对无需返回值的函数将使用void的形式且不使用return语句。

C++函数有库函数(标准函数)和自定义函数两类。

C++程序使用变量的基本规则是:必须先声明,后使用。

7 const修饰符和预处理程序

    C语言一般使用宏定义“#define”定义常量,在C++中,建议使用const代替宏定义。

因为被const修饰的变量的值在程序中不能被改变,所以在声明符号常量时,必须对常量符号进行初始化,除非这个常量是用extern修饰的外部变量。

Const的用处不仅仅是在常量表达式中代替宏定义。如果一个变量在生存期中的值不会改变,就应该用const来修饰这个变量,以提高程序安全性。

C++语言预处理程序不是编译程序的一部分,

为了与一般的C++程序语句相区别,所以有预处理语句都以位于首行的符号“#”开始。预处理语句有3种,分别是宏定义、文件包含和条件编译。

是使用双眼号还是尖括号,其含义并不一样。采用尖括号引用系统提供的的包含文件,C++编译系统将首先在C++语言系统设定的目录中寻找包头文件,如果没有找到,就到指定目录中去寻找。采用双引号引用自己定义的包含文件(一般都放在自己指定的目录中),这将天通知C++编译器在用户当前目录下火寻找包含文件。

8程序运行结果

9程序书写格式

(1)括号紧跟在函数名后面,但在for和while后面,应用一个空格与左括号隔开以增加可读性。

(2)数学运算符的左右各留意个空格,以与表达式区别。

(3)在表达参数时,逗号后面留个空格。

(4)在for、while和do…while语句中,合理使用缩进、一对花符号和空行。

(5)适当增加空行和程序注释以增加可读性。

(6)太长的程序行两行或者几行,并注意选取合适的分行和缩进位置。

1.2认识C++语言面向过程编程的特点

      C语言是典型的面向过程的语言。因为C++兼容了C语言,所以也可以使用C++编制面对过程的程序。

1.2.1使用函数重载

     C++允许为同一函数定义几个版本,从而使一个函数名具有多种功能,这称为函数重载。

1.2.2 新的数据类型 及其注意事项

     Void是无类型的标识符号,只能声明函数的返回值类型,不能声明变量。C++还比C语言多了bool(布尔)型。C++标准只限定int和short至少要有16位,而long至少32位,short不的长于int,int不得长于long。Visual C++ 6.0规定int使用4字节。

C++语言中的整数常量有4中类型:十进制常量、长整形常量、八进制常量和十六进字常量,并用前缀后缀进行分类标识。

 C++语言与C语言一样,也使用转义序列。

1.2.3 动态分配内存

1.2.4引用

数据类型&别名=对象名;

    “Int& a=x;”、“int & a=x;”是等效的

    所谓“引用”就是就是将一个新的标识和一块已经存在的存储区域的相关联。

(1)引用实际上就是变量的别名,使用引用就如同直接使用变量一样。引用与变量在使用的形式上是完全一样的, 引用只是作为一种标识的手段,不能直接声明对数组的引用,也不能声明引用的引用。

1.2.5 对指针使用const 限定符

    可以使用const限定符强制改变访问权限。

1左值和右值

    左值是指某个对象的表达式。

2指向常量的指针

    指向常量的指针式在飞常量指针前声明前面使用const,

3 常量指针

    把const限定符号放在*号的右边,使指针本身成为一个const指针。

4指向常量的常量指针

     可以声明指针和指向对向的对象都不能改动的“指向常量的常量指针”,这是必须要初始化指针。

1.2.6 泛型算法应用普通数组

     数组不能作为整体输出。

     入STL库提供的泛型算法,则可大大简化数组操作。所谓泛型算法,    就是提供的操作与元素类型无关。

   对数组进行排序为升幂或降幂,默认为升幂排序。要输出数组的内容、对数进行升幂排序、反转数组的内容、复制数组的内容等操作,需要包头文件。要对数组进行降幂排序和检索,需要包头文件。

假设一堆数组a和b的长度均为Len,数据类型为Type。

1数组内容反转

2复制数组的内容

3数组升幂排序

4数组降幂排序

5查找数组内容

6输出数组的内容

1.2.7数据的简单输入输出格式

1.3程序的编辑、编译和运行的基本概念

     用C++语言写程序称为源程序,源程序必须经过C++编译翻译成机器语言才能执行。

     (1)先使用编辑器编辑一个C++程序mycpp.cpp,又称其为C++的源程序。

     (2)然后使用编译器对这个C++程序进行编译,产生myccp.obj。

  (3)再使用连接程序(又称Link),将mycpp.obj变成mycpp.exe文件。

第二章

从结构到类的演变

2.1结构的演化

类是从结构演变而来的,开始称为“带类的C”。

2.1.1结构发生质的演变

1函数与数据共存

C++首先允许结构中可以定义函数,这些函数称为成员函数。如果将原来的结构成员称为数据成员的话,可以使用如下的形式描述:

Struct结构名{

       数据成员

       成员函数

};

最后一条语句则是直接使用数据成员,这称作结构point的共有(public)性质。

2封装性

如果在定义结构时,将数据成员使用private关键定义,则产生封装性。

没有使用private定义的成员函数,默认为public。

这就变成了具有类的性质的结构。只是类使用关键字class定义,它默认的是private。

2.1.2使用构造函数初始化结构对象

构造函数名 对象名(初始化参数);

2.2从结构演变一个简单的类

2.3面向过程与面向对象

所谓“面向过程”,就是不必了解计算机的内部逻辑,而把精力主要集中在对如何求解问题的算法逻辑和过程的描述上,通过编写程序把解决问题的步骤告诉计算机。

(1)要求开发人员按计算机的结构去思考,而不是按解决的问题结构去思考。

(2)开发员必须在机器模型(解空间)和实际问题模型(问题空间)之间进行对应。

结构化程序设计使用的是功能抽象,面向对象程序设计不仅能进行功能抽象,而且能进行数据抽象。

面向对象的程序设计方法不是以函数过程和数据结构中心,而是以对象代表求解问题的中心环节。

软件开发是给定问题求解的过程。从认识论的角度看,可以为两项主要活动:认识与描述。

2.4 C++面向对象程序设计的特点

面向对象的程序的设计具有抽象、封装、继承和多肽型等关键要要数。

2.4.1 对象

C++可使对象名、属性和操作三要素来描述对象。对象名用来标识一个具体对象。用数据来标是对象的属性,一属性就是描述对象静态的特征的一个数据项。

数据称为数据成员,函数称为函数成员。

C++中的对象是系统中用来描述客观事物的一个实体,是构成系统的一个基本单位。

2.4.2 抽象和类

2.4.3 封装

将类封装起来,也是为保护类的安全。所谓的安全,就是限制使用类的属性和操作。

对象的操作分为内部操作和外部操作。内部操作只供对象的其他操作使用,不对外部提供。外部操作对外部提供一个消息接口,通过这个接口接受对象外部消息并为之提供操作(服务)

封装就是把对象的属性和操作结合称一个独立的系统单元,并紧可能的隐蔽对象的内部细节。

2.4.4 继承

继承是一个类可以得另一类特性的机制,继承支持层次概念。

2.4.5 多态性

不同的对象可以调用相同的函数,但可导致完全不同的行为的现象称为多态性。

2.5 使用类和对象

2.5.1使用string的对象

在程序中可以使用string类定义存储字符串的对象。

如果string的对象str的内容为“ab”,则str[0]=‘a’,str[1]=‘b’。

Strl。Size()的值为单词‘good’的长度。

2.5.2 使用string类的典型成员函数实例

     String对象是通过调用成员函数实现操作,从而提供对象的行为或消息传递的。

2.5.3 使用complex对象

C++标准程序库提供complex类定义复数对象。在程序中包含这个类的头文件:

Complex类是一个模版类,所谓模版,意思是说,它可以定义多种数据类型的复数。

第三章

函数和函数模板

3.1函数的参数及其传递方式

C语言函数参数的传递方式只有传值一种,传值又分为传变量和传变量地址值两种情况。

参数传递中不要混淆传地地址值和传地址的区别。传地址的是值,不是地址;传地址传的是地址不是地址值。

在设计函数参数是,可以使用“对象”、“对象指针”和“对象引用”作为参数。

3.1.1对数作为函数参数

将对象作为函数参数,是将实参对象的值传递给形参对象,这种传递是单向的。形参拥有实参对象的备份,当在函数中改变形参的值时,改变的是这个备份中的值,不会影响原来实参的值。

直接使用基本数据类型的对象,或使用和结构的对象作为参数,均是传值的方式。不能数组的值作为函数参数,但可以将数组的地址作为参数,即使用指针作为参数。

3.1.2对象指针作为函数参数

将指向对象的指针作为函数参数,形参是对象指针(指针可以指向对象的地址),实参是对象的地址值。

3.1.3引用作为函数参数

可以使用“引用”作为函数的参数“引用形参”。这时函数并没有对形参对象初始化,即没有指定形参对象是哪个对象别名。

虚实结合是把实参对象的地址传给形参对象,使形参对象的地址取实参对象的地址,从而使形参对象和实参对象共享同一个单元。这就是地址传递方式。为了便于理解,可以简单地认为是把实参对象的名字传给引用对象,使引用对象称为实参对象的别名。

在说明引用参数时,不需要提供初始值,其初始值在调用时有实参对象提供。

3.1.4默认参数

默认参数就是不要求程序员设定该参数,而又编译在需要时给该参数赋默认值。当程序员需要传递特殊值时,必须显式地指明。默认参数是在函数原型中说明的,

3.1.5使用const保护数据

用const修饰传递函数,意思是通知函数,它只能使用参数而无权修改它。

3.2深入讨论函数返回值

C++函数的返回值类型可以是除数组和函数以外的任何类型。非void类型的函数必须向调用者返回一个值。数组只能返回地址。

因此不能将函数内部的局部对象作为函数的返回值。

3.2.1返回引用的函数

3.2.2返回指针函数

3.2.3返回对象的函数

3.2.4函数返回作为函数的参数

3.3内联函数

使用关键字inline说明函数称内联函数。在C++中,除具有循环语句、switch语句的函数不能说明为内联函数外,其他函数都可以说明为内联函数。使用内联函数能加快程序执行速度,但如果函数体语句多,则会增加程序代码的大小。使用小的内联函数在代码速度和大小可以取得折衷,

3.4函数重载和默认参数

函数重载可是一个函数名具有多功能,即具有“多种形态”,称这种特性为多态性。

从函数原型可见,它们的区别一是参数类型不同,二是参数不同。

使用默认参数就不能对少于参数个数的函数进行重载。

3.5函数模板

1引入函数模板

因为字母T能使人联想到它是单词Type的第一个字母,所以一般选T作为标识符号来标识类型参数,即参数名可以任意挑选的。规定模板一template关键字和一个形参表开头。

2函数模板的参数

函数模板名<模板参数>(参数列表)

函数模板(参数列表)

3 使用显式规则和关键字typename

另外,C++还专门定义一个仅仅用在模板中的关键字typename,它的用途之一是代替template参数列表中的关键之class。

第四章

类和对象

4.1类及其实例化

4.1.1定义类

类也要先声明后使用;不管声明的内容是否相同,声明同一个名字的两个类是错误的,类是具有惟一标识的实体;在类中声明的任何成员不能使用extern、auto和register类关键字进行修饰;类中声明变量属于该类,在某些情况下,变量也可以被该类的不同实例所共享。

1声明类

Private:私有数据和函数

Public:公有数据和函数

Protected:保护数据和函数

如果没有使用关键字,则所有成员默认声明为private权限。其中“∷”是作用域运算符,“类名”是成员函数所属类的名字,“∷”用于表明其后的成员函数是属于这个特的类。

3数据成员的赋值

不能再体内给数据成员赋值

4.1.2使用类的对象

(1)类的成员可以直接使用自己类的私有成员

(2)类外面的函数不能直接访问类的私有成员

(3)类外面的函数只能通过类的对象使用该类的共有成员函数。

(4)对象A和B的成员函数的代码一样,A和B两个对象的区别是属性的取值。

4.1.3 数据封装

C++对其对象的数据成员和数据函数的访问控制权限来限制的。

C++通过类实现数据封装

4.2构造函数

4.2.1默认构造函数

一旦程序定义了自己的构造函数,系统就不在提供默认函数。

因为每个元素对象均需要用一次默认构造函数来自己初始化,所以必须要求有一个默认构造函数。如果程序中定义了有参数的构造函数,又存在需要先建立对象数组后进行赋值操作的情况,则必须为它定义无参数的结构函数。

4.2.2 定义构造函数

1构造函数的定义和使用方法

构造函数的参数在排列时无顺序要求,只要保证相负对应即可。可以使用默认参数或重载。

2自动调用构造函数

4.2.3构造函数和运算符new

运算符new用于建立生存期可控对象,new返回这个对象指针。

当使用new建立一个动态对象时,new首先分配足以保存point类的一个对象所需要的内存。

4.2.4 构造函数的默认参数

4.2.5复制构造函数

这是一类特殊而且重要的函数通常用于使用已有的对象来建立一个新对象。

对象建立新对象,译为拷贝构造函数。

4.3析构函数

在对象消失时,应使用析构函数释放构造函数分配的内存。

4.3.1定义析构函数

因为调用析构函数也是由编译器来完成的所以编译器必须总能知道应调用哪个函数析构函数的前面加上一个“~”号。

析构函数不能指定参数,但是可以显式地说明void,

一个类也这能定义一个析构函数且不能指明参数,

4.3.2 析构函数和运算符delete

4.3.3默认析构函数

4.4调用复制构造函数的综合实例

4.5成员函数重载及默认参数

4.6this指针

4.7一个类的对象作为另一类的成员

距形类Rectangle的属性需要一个座标点及长和宽。一个point的对象恰好可以作为矩形的顶点座标,即Rectangle可以使用point的一个对象作为数据成员。

4.8类和对象的性质

(1)同一类的对象之间可以相互赋值。

(2)可使用对象数组。

(3)可使用指向对象的指针,使用取地址运算符&将以个对象的地址置于该指针中。

(4)对象用作函数参数。

(5)对象作为参数时,可以使用对象、对象引用和对象指针。

(6)一个对象可以做另一个类的成员。

4.8.2类的性质

1使用类的权限

1假设声明了point类,为了简单具体,讨论数据成员为私有,成员函数为公有情况。

(1)类本身成员函数可以使用类所以成员(私有和公有成员)。

(2)类的对象只能访问公有成员函数

(3)其他函数不能使用类的私有成员,也不能使用公有成员函数,它们只能通过类的对象使用公有成员函数。

(4)虽然一个类可以包含另一个类的函数对象,但这个类也只能通过被包含类的对象使用那个累的成员函数,通过成员函数使用数据成员。

2不完全类声明

使用struct关键字设计类时,struct与class相反,struct的默认控制权限是public。一般建议不用struct设计类

4.9面向对象的标记图

4.9.1类对象的UML标记图

类使用短式长式两种方式表示。短式仅用1个含义类名的长方框表示。

4.9.2对象的结构与连接

只有定义和描述了对象之间的关系,各个对象才能构成一个整体的、有机的系统模型,这就是对象的结构域连接关系。对象结构是指对象之间的分类(继承)关系和组成(集合)关系,统称为关联关系。

1分类关系及其表示

2对象组成关系及其表示

组成关系说明的结构是整体与部分关系。C++中最简单的是包含关系,

C++语言中的“聚合”隐含了两种实现方式,第1种方式独立地定义,可以属于多个整体对象,

第2中方式是用以个对象作为一种广义的数据类型来定义整体对象的一个属性,

3实例连接及其表示

一对一、一对多和多对多3种连接方式。

4消息连接及其表示

消息连接描述对象之间动态关系

消息连接时有方向的,使用一条带箭头的实线表示从消息的发送者指向消息的接受者。

4.9.3使用实例

1 Line类包含point类

2 Line类的继承point类

4.9.4 对象、类和消息

对象的行为是定义在对象属性上的一组操作的集合。操作(函数成员)是响应消息而完成的算法,表示对象内部实现的细节。对象的操作和体现了对象的行为能力。

对象的属性和行为是对象定义组成的要数,

(1)有一个状态,由与其关联的属性值集合所表征

(2)惟有一标识名,可以区别于其他对象。

(3)有一组操作方法,每个操作决定对象的一种行为。

(4)有一组状态只能被自己的行为所改变。

(5)对象的操作包括自身操作(施加与自身)和施加于其他对象的操作。

(6)对象之间以消息传递的方式进行通信。

(7)一个对象的成员可以是一个对象。

消息是向对象发出的服务请求,它是面向对象系统中实现对象间的通信和请求任务的操作。

对象传递的消息一般有3部分组成:接收对象名、调用操作名和必要的参数。

4.10面向对象编程的文件规范

    实现放在.cpp文件中。在.cpp文件中

4.10.1编译指令

所有的编译指令以#开始,每条指令单独占用一行,同一行,同一行不能有其他编译指令和C++语句。

1嵌入指令

2宏定义

#define的指令定义一个标识符串,在员程序中每次遇到该标识符时,编译器均用定义的字符串替之。每行的行尾要加上一个方斜线,表示在宏定义继续到下一行。

因宏定义有许多不安全因素,对需要使用无参数宏的场合,应该尽量使用const代替宏定义。

如果不想使其影响到程序的其他地方,可以在不再使用时用#undef删除。

3条件编译指令

条件编译指令是#if、#else和#endif,它们构成类似于C++的if选择结构,其中#endif表示一条指令结束

4defined操作符

关键字defined不是指令,而是一个预处理操作符。用于判定义个标识符是否已经被#defined定义。

条件编译指令#ifdef和ifndef用于测试其后的标识符是否被define定义,如果已经被定义,则#ifdef测试为真,#ifdef测试为假,#ifindef测试为真。

4.10.2在都文件中使用条件编译

第五章

特殊函数和成员

5.1对象成员的初始化

如果初始初始化列表某项的参数函数表为空,则列表相应的项可以省略

对象成员构造函数的调用顺序取决于这些对象成员在类中的说明顺序。

析构函数的调用顺序与构造函数正好相反。

5.2静态成员

简单成员函数是指声明函数不含const、volatile、static关键字的函数。如果类的数据成员或成员函数使用关键字static进行修饰,这样的成员称为静态成员或静态成员函数,统称为静态成员。

静态数据成员能说明一次,如果在类中仅对静态数据成员进行声明,则必须在文件作用域的某个地方进行定义。在进行初始化时,必须进行成员名限定。

除静态成员的初始化之外,静态成员遵循类的其他成员函数所遵循的访问限制,

由于数据隐蔽的需要,静态数据成员通常被说明为私有的,

通过成员限定访问静态成员,比使用对象名访问静态成员要好,因为静态成员是类的成员而不是对象的成员。

类中的任何成员都可以访问静态成员。因为静态成员函数没有this指针,所以静态成员函数只能通过对象名(或指向对象的指针)访问该对象的非静态成员。

(1)可以不指向某个具体的对象,只与类名连用。

(2)在没有建立对象之前,静态成员就已经存在。

(3)静态成员为类的成员,不是对象的成员。

(4)静态成员为该类的所有对象共享,它们被存储于一个公用内存中。

(5)没有this指针,所有除非显式地吧指针传给它们,否则不能存取类的数据成员。

(6)静态成员函数不能被说明为虚函数。

(7)静态成员函数不能直接访问非静态函数。

关键字static声明的类的对象,但要注意它的构造函数与析构函数的调用特点。

5.3友员函数

友员函数可以存取私有成员、公有成员和保护成员。

1.类本身的友元函数

2.将成员函数做有元

3.将一个类说明为另一个类的友元

友元关系是不传递的即当说明类A是类B的友元,类B又是类C的友元时,

5.4 const对象

    可以再使用const关键字定义数据成员和成员函数和修饰一个对象。一个const对象只能访问const成员函数。

1常量成员

常量成员包括常量数据成员、静态常数据和引用。静态常数成员仍保留静态成员特征,需要在类外初始化。常数据成员和常引用只能通过初始化列表来获得初值。

2常引用作为函数参数

使用引用作为函数参数,传送的是地址。

3常对象

在对象名前使用const声明常对象,但声明是必须同时进行初始化,而且不能被更新。

4常成员函数

一个const对象可以调用const函数,但不能调用非const成员函数。Const放在函数声明之前意味着返回值是常量,

为了保证不仅声明const成员函数,而且确定也定义为const函数,程序员在定义函数时、必须重申const声明。

普通对象可以使用全部成员函数,但常量对象只能使用常量函数。

5.5 数组和类

5.6指向类成员函数的指针

C++既包含指向类数据成员的指针,又包含指向成员函数指针。

类并不是对象,但有时可将其视为对象使用。可以声明并使用指向对象成员函数的指针。

5.7 求解一元二次方程

5.7.1 设计代表方程的类

5.7.2设计成员函数

1.设计构造函数

2.设计成员函数

5.7.3编程实现

1设计工程和文件

2头文件

3实现类

5.7.4使用VC编制完整的文件

5.7.5 运行示范

第六章

继承和派生

6.1继承和派生的基本概念

类的派生和继承是面向对象 程序设计方法和C++语言最重要的特征之一

从一个活多个以前定义的类(基类)产生新类的过程称为派生类。

派生的新类同时也可以增加或者重新定义数据和操作,这就产生了类的层次性。

类的继承是指派生类继承基类的数据成员函数。

当从现有类中派生出新类是

(1)增加新成员

(2)重新定义已有的成员函数。

(3)改变基类成员的访问权限。

6.2 单一继承

6.2.1 单一继承的一般形式

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

构造函数(包括析构函数)是不被继承的,所以一个派生类只能调用它的直径基类的构造函数。当定义派生类的对象时,首先调用基类的机构函数,对基类成员进行初始化

6.2.3 类的保护成员

6.2.4访问权限和赋值兼容规则

1公有派生和赋值兼容规则

(1)基类的公有成员在派生类中仍然是公有的。

(2)基本的保护成员在派生类中仍然是保护的。

(3)基类的不可以访问的和私有的成员在派生类中也仍然是不可访问的。

但是在派生类中,可以存在滴4种访问级别:不可访问(inaccessible)。

所谓赋值兼容规则是指在公有派生情况下,一个派生类的对象可以作为基类的对象来使用的情况。

(1)派生的对象可以赋给基类的对象。

(2)派生类的对象可以初始化基类的引用。

(3)派生类的对象的地址可以赋给指向基类的指针。

2“isa”和“has-a”的区别

如果写成类B公有继承于类A,在可以使用A对象的让任何地方,则类B的对象通信业能使用,因为每一个类B的对象”“就是一个”类A的对象。

3公有继承存取权限表

派生类一般都使用公有继承。使用基类本身、派生类、对象和外部函数,对派生类而言,使用它的有派生类本身、对象和外部函数。

注意:静态成员可以被继承,这时,基类对象和派生的对象共享该静态成员。

4私有派生

通过私有派生,基类的私有和不可访问成员在派生类中是不可以访问的,而公有和保护成员这时就成了派生类私有成员,派生类的对象不能访问继承的基类成员,必须定义公有函数作为接口。

6.3多重继承

6.4二义性激情支配规则

对基类成员的访问必须是无二义性的,如使用一个表达式的含义能解释为可以访问多个基类的成员,则这种对基类成员的访问就是不确定的,称这种访问具有二义性。

6.4.1 作用域分辨和成员名限定

6.4.2 派生类支配基类的同名函数

6.5 典型问题分析

1派生类没有使用基类的数据成员

2派生类支配基类的同名函数

3二义性

4友元和派生类

友元声明与访问控制无关。友元声明在私有区域进行或在公有区域进行是没有太大区别的。

第七章

类模板与向量

7.1类模板

7.1.1类模板基础知识

1.类模板的成分及语法

Template<类模板参数>class类名{//类体};

2 类模板的对象

类模板也称为参数化

类名<模板实例参数类型>对象名(构造函数实例参数列表);

类名<模板实例参数类型>对象名;//默认或者无参数构造函数

Template<模板参数>

返回类型 类型<模板类型参数>∷成员函数名(函数参数列表){//函数体}

7.1.2类模板的派生于继承

类模板也可以继承,继承的方法与普通的类一样。声明模板继承之前,必须重新声明类模板。模板类的基类和派生类都可以是模板(或非模板)类。

7.2 向量与泛型算法

在数组生存期内,数组的大学、小不会改变的。向量是一维数组的类版本,它与数组相似,其中的元素项是连续存储的,但它和数组不同的是:向量中存储元素的多少可以再运行中根据需要动态地增长或缩小。向量是类模板具有成员函数,

7.2.1定义向量列表

向量(vector)类模板定义在文件vector中,它提供4种构造函数,用来定义有各元素组成的列表。用length表示长度,数据类型用type表示,对象名为name,

7.2.2泛型指针

“与操作对象的数据类型相互独立”的算法称为泛型算法。

泛型算法提供了许多可用于向量的操作行为,而这些算法和想要操作的元素类型无关。这是借助一对泛型指针来实现的。

在向量中,泛型指针是在底层指针的行为之上提供一层抽象化机制,取代程序原来的“指针直接操作方式”。

7.2.3 向量的数据类型

7.2.4 向量最基础的操作方法

向量有许多成员函数用来提供不同的操作,

1访问向量容量信息的方法

(1)Size():返回当前向量中已经放的对象个数。

(2)Max_size():返回向量可以可以容纳最多的对象个数,一般是操作系统的寻址空间锁能容纳的对象个数。

(3)Capacity():返回无需再次分配内存就能容纳的对象个数。

(4)Empty()当前向量为空时,返回true值。

2访问向量中对象的方法

(1)front()返回向量中的第1个对象。

(2)Back():返回向量中的最后一个对象。

(3)Operator[]:(size_type,n):返回向量中的第n+1个对象(下标为n的向量元素)。

7.2.4向量最基础的操作方法

7.3 出圈游戏

1设计类

2主函数

3源程序

第八章

多态性和虚函数

8.1多态性

静态联编所支持的多态性称为编译时的多态性。动态联编所支持的多态性称为运行时的多态性,

8.1.1静态联编中的赋值兼容性及名字支配规律

8.1.2 动态联编的多态性

如果让编译器动态联编,也就是在编译“point*P=&c;”语句时,只根据兼容性规则检查它的合理性,也就是检查是否符合“派生类对象的地址可以赋给基类的指针”的条件。至于“p->area()”

调用哪个函数,等程序运行到这里时再决定。

就要使类point的指针p指向派生类函数area的地址。假设使用关键字virtual声明point的类area函数,将这种函数称为虚函数。

当编译系统编译含有虚函数的类时,将为它建立以个虚函数表,表中的每个元素都指向一个虚函数地址。编译器为类增加一个数据成员,这个数据成员是一个指向该虚函数表的指针,通常称为vptr。

虚函数的地址翻译取决于对象的内存地址。编译器为含有虚函数的类的对象建立一个入口地址,这个地址用来存放指向虚函数表的指针vptr,然后按照类中的虚函数声明次序,一一填入函数指针。

派生类能继承基类的虚函数表,而且只要是和类同名(参数也相同)的成员函数,无论是否使用virtual声明,它们都自动成为虚函数。如果派生类没有改写基类的虚函数,则函数指针调用基类的虚函数。如果派生改写了基类的函数,编译器将重新为派生类的虚函数建立地址,函数指针会调用改写过的虚函数。

虚函数的调用规则是:根据当前对象,优先调用对象本身的虚成员函数。

8.2 虚函数

    一旦基类定义了虚函数该基类的派生类中的同名函数也自动成为虚函数。

8.2.1 虚函数

函数只能是类中的一个成员函数,但不能使静态成员,

8.2.2 虚函数实现多态的条件

关键字virtual指示C++编译器对调用虚函数进行动态联编。这种多态性是程序运行到需要的语句处才动态确定的,所以称为运行时的多态。

(1)类之间的继承关系满足赋值兼容规则。

(2)改写同名虚函数

(3)根据赋值兼容性规则使用指针

满足钱联条件不一定产生动态编译,必须同时满足第3条才能保证实现动态编译。第3友分为两种情况:第1中是已经演示过的按赋值兼容性规则使用基类指针(或引用)访问虚函数;第2种是把指针(或引用)作为函数参数,即这个函数不一定是类的成员函数,可以是普通函数,而且可以重载。

8.2.3构造函数和析构函数调用虚函数

在构造函数和析构函数中调用虚函数采用静态联编,

在建立类C的对象c时,它所包含的基类对象在派生类中定义的成员建立之前被建立。在对象撤销时,该对象所包含的在派生类中定义的成员要先于基类对象之前撤销。

目前推存的C++标准不支持虚构函数。有于析构函数不允许有参数,因此一个类只能有一个虚析构函数。虚析构函数使用vitual说明。

Delete运算符合析构函数一起工作(new和构造函数一起工作),当使用delete删除一个对象时,delete隐含着对析构函数的一次调用,如果析构函数为虚函数,则这个调用采用动态联编。

8.2.4纯虚函数与抽象

Virtual 函数类型 函数名(参数列表)=0;

一个类可以说明多个纯虚函数,包含有纯虚函数的类称为抽象类。

如果通过同一个基类派生一系列的类,则将这些类总称为类族。

抽象至少含有一个虚函数,而且至少有一个虚函数是纯虚函数,

8.3 多重继承于虚函数

8.4类成员函数的指针与多态

在派生类中,当一个指向某基类成员的指针向一个虚函数,并且通过指向对象的基类指针(或引用)访问这个虚函数时,仍发生多态性。

第九章

运算符重载及流类库

9.1 运算符重载

9.1.1 重载对象的赋值运算符

这个成员函数必须使用引用参数,“赋值函数”使用符号“operator=”表示,C++的关键字“operator”和运算符一起使用就表示一个运算符函数,

9.1.2运算符重载的实质

为用户定义的类型重载运算符都要求能够访问这个类型的私有成员,所以只有两条路可走:要么将运算符重载为这个类型的成员函数,要么将运算符重载为这个类型的友元。

C++的运算符大部分都可以重载,不能重载的只有.、∷、*和?:。前面3个是因为在C++中有特定的含义,不准从重载避免不必要的麻烦;“?:”则是因为不值得重载。另外,“sizeof”和“#”不是运算符,因而不能重载,而=、()、[]、->这4个运算符只能用类运算符来重载。

9.1.3《、》和++运算符重载实例

9.1.4 类运算符和友元运算符的区别

如果对象作为重载运算符函数的参数,则可使用构造函数将常量转换成该类型的对象。如果使用引用作为参数,因为这些常量不能作为对象名使用,所以编译系统就要报错。

成员运算比友元运算符少一个参数,这是因为成员函数具有this指针。Complex&a是形参表,a是类complex的引用对象,所以使用对象名。

9.1.5下标运算符“[]”的重载

9.2流类库

9.2.1流类库的基础类

在C++中,输入输出是通过流来完成的。C++的输出操作将一个对象的状态转换成一个字符序列,输出到某个地方。

接收输出数据的地方叫做目标,把输入数据来自的地方叫源。

这个执行输入和输出操作的体系就叫做流类,提供这个流类实现的系统库就叫做流类库。

这些基础类在头文件中说明。

在C++中,如果在多条件继承路径上有一个汇合处,则称为这个汇合处的基类为公共基类(ios类符合条件)。

C++的流类库预定义了4个流它们是cin、cout、cerr、和clog。事实上,可以讲cin视为类istream的一个对象,而将cout视为类otream的对象。

9.2.2默认输入输出格式控制

9.2.3 使用ios_base类

1ios_base类简介

这些常量提供成员函数ios_base、∷setf(fmtflage)来设置类的格式。格式标志存放在每个流的一个长整形成员中,每个标志占1位,在ios_base类中定义。

2直接使用格式控制

3使用成员函数

9.3文件流

9.3.1 使用文件流

流类具有支持文件的能力,在建立和使用文件时,就像使用cin和cout一样方便。

假如建立一个类似cout以样使用myFile只要myFile也是ofstream类型对象,就可像使用cout一样,使用myFile将指定内容希尔文件。

(1)打开一个相应的文件流。

(2)把这个刘和相应的文件关联起来。

(3)操作问了流

9.3.2几个典型流成员函数

    1输出的open函数

    2输入流类的open函数

    3close成员函数

    4错误处理函数

9.3.3文件存取综合实例

    1头文件studebt.H

    2源文件student .cpp

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章