C++的面向对象基础知识课件_第1页
C++的面向对象基础知识课件_第2页
C++的面向对象基础知识课件_第3页
C++的面向对象基础知识课件_第4页
C++的面向对象基础知识课件_第5页
已阅读5页,还剩79页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C++的面向对象基础知识

11.1传统的程序设计方法

一.程序设计方法的进步

在20世纪60年代,软件曾出现过严重危机,由软件错误而引起的信息丢失、系统报废事件屡有发生。为此1968年,荷兰学者提出了程序设计中常用的GOTO语句的三大危害:破坏了程序的静动一致性;程序不易测试;限制代码化。此举引起了软件界长达数年的论战,并由此产生了结构化程设计方法,同时诞生了基于这一设计方法的程序设计Pascal.Pascal一经推出,它的简洁明了以及丰富的数据结构和控制结构,为程序员提供了极大的方便性与灵活性,同时它特别适合计算机系统,因此大受欢迎。结构化程序设计思想在整个20世纪70的软件开发中占绝对统治地位。二.什么是结构化程序设计(StructureProgramming)

结构化程序设计是上个世纪60年代诞生的,在70年代到80年代已遍及全球,结构化程序设计的设计思路是:自顶向下、逐步求精;其程序结构是按功能划分若干个基本模块,这些模块形成一个树状结构;各模块之间的关系尽可能简单,在功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成;结构化程序设计方法的四条原则是:1.自顶向下;2.逐步求精;3.模块化;4.限制使用goto语句。

当数据和过程相互独立时,总存在着用错误的数据调用正确的程序模块或用正确的数据调用了错误的程序模块的可能性。因此,要使数据与程序始终保持相容,已经成为程序员的一个沉重负担。上述这些问题,结构化程序设计方法本身是解决不了的,到了70年代末期,结构化程序设计语言和结构化分析与设计已无法满足用户需求的变化,于是面向对象技术开始浮出水面。11.1.2面向对象的程序设计方法

一.面向对象的由来和发展

面向对象方法起源于面向对象语言,编程语言得到应用和发展的同时,面向对象的方法得到了发展。和任何事物一样,面向对象语言也经历了它的发生、发展阶段,走向成熟。1.在60年代初期,Algo语言使封装思想诞生。2.在60年代后期,Simula引入对象和消息机制,对象和对象之间可以通过发送消息来进行相互通信,这就是导致了数据封装与通信思想的产生。

3.到了70年代,都许多语言如CLU、Ads、Modula-2等都开始支持数据与封装,这导致了抽象数据类型发展。4.1980年,出现Smalltalk-80商品化的面向对象语言,它是纯粹的面向对象编程语言。5.80年代中期到90年代,出现了大批面向对象语言,面向对象语言趋于成熟,从此面向对象方法走向实用。二.面向对象的基本思想

其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。三.面向对象的基本概念

1.对象:特性+行为

第一个面向对象的程序设计语言是60年代开发的Simula—67。其目的是为了解决模拟问题。典型的模拟问题是银行出纳业务,包括出纳部门、顾客、业务、货币的单位等大量的“对象”。把那些在程序执行期间除了状态之外其他方面都一样的对象归在一起,构成对象的“类”,这就是“类”一词的来源。类描述了一组有相同特性(数据元素)和相同行为(函数)的对象。2.继承:类型关系

特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。一个类可以是多个一般类的特殊类,它从多个一般类中继承了属性与服务,这称为多继承。例如,客轮是轮船和客运工具的特殊类。在java语言中,通常我们称一般类为父类,特殊类为子类。3.封装性

封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义:把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界,只保留有限的对外接口使之与外部发生联系。4.多态性

对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。11.2C++对C的扩充

11.2.1C++语言源程序的编译

为了解C++语言源程序的编译过程首先介绍一些基本术语:

1.源程序:用源语言写的有待翻译的程序,称为“源程序”。源程序可以是汇编语言,也可以是高级程序设计语言,所以用它们写出的程序都是源程序。

2.目标程序:是源程序通过翻译加工以后所生成的程序。目标程序可以用机器语言表示,也可以用汇编语言或其他中间语言表示。

3.翻译程序:是指用来把源程序翻译为目标程序的程序。对翻译程序来说,源程序是它的输入,而目标程序则是其输出。11.2.2基本数据类型

1.C++类型分类C++的数据类型有基本数据类型和非基本数据类型。基本数据类型是C++内部预先定义的数据类型。主要有整型、字符型、实型、布尔型这四种基本类型。非基本数据类型包括指针、数组、结构、类等。2.整型标准C++中6种整型short、int、long、unsignedshort、unsignedint、unsignedlong。以在十六位计算机中表示为例它们的范围如下表11.2-1:类型说明长度(字节)范围short短整型2-32768~32767int整型2-32768~32767llong长整型4-2147483648~2147483647unsignedshort无符号短整型20~65535unsignedint无符号整型20~65535unsignedlong无符号长整型40~42949672953.字符型字符文字由单引号‘限定,字符值以整型的方式存储。【例11.1】字符变量intmain(){//打印字符和已在内部存储的整型值charc=ˊAˊ;cout<<"c="<<c<<",int(c)="<<int(c)<<endl;c=ˊtˊ;cout<<"c="<<c<<",int(c)="<<int(c)<<endl;}运行结果:c=A,int(c)=65c=t,int(c)=116由于字符值被用于输入和输出,因此它们表现为字符的形式而不是整型的形式:字符A是以字母A的形式而不是以它的内部表示的整数值65的形式被打印出来。程序中用类型转换运算符int()将其内部对应的整型值展示出来。这就是字母的ASCII码。字符型的范围如下表11.2-2:类型说明长度(字节)范围char字符型1-128~127unsignedchar无符号字符型10~2554.实型C++支持3种实数型:float、double、longdouble。在大多数系统中,double使用float两倍的字节数。典型的是float使用4字节,double使用8字节,longdouble使用8、10、12或16字节。实型的范围如下表11.2-3:类型说明长度(字节)float浮点型4double双精度型8Longdouble长双精度型105.布尔型

布尔型变量只能取两个值:false和true。这两个值被存为0和1。标准C++中,布尔型被称为bool。【例11.3】布尔类型变量

intmain(){//打印布尔变量的值

boolflag=false;

cout<<"flag="<<flag<<endl;

flag=true;

cout<<"flag="<<flag<<endl;

}运行结果:flag=0flag=1注意false值被打印成整数0而true值被打印成整数1。6.数据类型转换c++中数据类型转换有两种,即隐式类型转换和显式类型转换。隐式类型转换由编译器自动完成,当编译器遇到不同类型的数据参与同一运算时,会自动将它们转换成相同类型后在进行运算。隐式类型转换按从低到高的顺序进行。显式类型转换它是程序员显式指出的类型转换,转换形式有两种:〈类型名〉(表达式)(〈类型名〉)表达式通过类型的显式转换可以将“表达式”转换成适当的类型。11.2.3变量的定义

变量名要遵守以下规则:1)不能是C++保留字。

2)第一个字符必须是字母或下划线。

3)中间不能有空格。

变量就是值可变的量,每个变量由一个变量名唯一标识,同时,每个变量又具有一个特定的数据类型。类型标志着这个变量将来的用法以及它将保存哪种类型的数据值。命名变量名

可以在一个语句里建立多个同一类型的变量,方法是在类型后写上多个变量名,中间用逗开。例如:

unsignedmyage,myweight;

longarea,width,length;

在同一语句里不能混合定义不同类型的变量

3.变量赋值与初始化

用赋值运算符“=”给变量赋值。例如:intdepth;depth=5;也可在定义时直接给变量赋值。在定义的同时,赋给变量一个初始值,称为变量的初始化。例如:intdepth=5;//初始化

在定义时也可以初始化多个变量。例如:intdepth=5,length=6;不是所有的变量在定义时都需要初始化。例如:doublearea,radius=15;该变量定义并不是将15同时赋给这两个变量,而是变量radius初始化为15,area只是定义,没有被初始化。4.用typedef定义自己的变量类型

在C++中可以利用typedef定义自己的变量类型,其形式为:typedef〈类型说明〉;〈类型说明〉类似于变量说明,只是变量名用类型名代替了,实际上,这等于定义了一个同义词,这种方式与创建一个新的类型是不同的。Typedef没有实际地定义一个新的数据类型,在建立一个typedef类型时没有分配内存空间。例如:

typedef

intdepth;

typedefcharstring[8];

使用自定义类型有几点好处:一是可以更好地表达程序员的意思,如用depth来表示将要定义的标识符是属于深度一类的数据,用string表示程序员想要定义的是一个字符串,这比直接用系统预定义的类型清晰得多;二是简单方便,一些数据类型可以用简单的类型标识符来表示,不用每次都麻烦地写复杂的定义。1.4.4C++的函数原型

函数原型是一条程序语句,它由函数返回类型﹑函数名和参数表构成,形式为:返回类型函数名(参数表);在C++中,函数声明就是函数原型。在C++中,函数的声明可以在主程序以前,也可以在主程序之後。程序:使用函数C++版本(函数的声明在主程序以前)如果函数在主程序之后声明,在主程序以前必須有一個叫做函数原型的語句。函数原型告訴C++編譯程序参数的数据類型、参数的数目及函数回传的数据類型,這些資料必須和函数的声明一致。在数据原型中,参数名称是不需要的,就算有也不一定要和函数声明的一样。例如,函数原型

floatpower(floatbase,intn);

可以寫成

floatpower(float,int);

11.2.5常量说明

一.常类型const

常数型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。因此,定义或说明常类型时必须进行初始化.

二.常量分类

1.一般常量

2.常对象

3.常指针1.一般常量一般常量是指简单类型的常量。

定义或说明一个常数组可采用如下格式:

<类型说明符>

const

<数组名>[大小]或者const

<类型说明符>

<数组名>[大小]例如:int

const

a[5]={1,2,3,4,5};2.常对象

常对象是指对象常量,定义格式如下:<类名>

const

<对象名>或者const

<类名>

<对象名>

定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面.

3.常指针

下面定义的一个指向字符串的常量指针:char

*

const

prt1

=stringprt1;其中,ptr1是一个常量指针.下面赋值是非法的:ptr1=stringprt2;而下面的赋值是合法的:*ptr1="m";因为指针ptr1所指向的变量是可以更新的,不可更新的是常量指针ptr1所指的方向(别的字符串).11.2.6C++的注释语句一.什么是注释注释是程序员为读者作的说明,是提高程序可读性的一种手段.一般可将其分为两种:序言注释和注解性注释.前者用于程序开头,说明程序或文件的名称,用途,编写时间,编写人及输入输出说明等,后者用于程序中难懂的地方.二.二.注释的书写

1.C++风格的注释为"//"之后的内容,直到换行.注释仅供阅读程序使用,是程序的可选部分.在生成可执行程序之前,C++忽略注释,并把每个注释都视为一个空格.2.另外,C++还兼容了C语言风格的注释,是指符号"/*"与"*/"之间的任何字符串,这些字符可以跨过多行.

11.2.7C++的标准I/O操作

所有用到标准输入输出的C++程序都必须包含iostream这个预处理伪指令.标识符iostream是标准C++库中一个文件的名字.格式为:include<iostream.h>.

iostream.h是系统定义的一个头文件,它设置了C++的I/O相关环境,定义输入输出流对象cout与cin等.

一.输出

二.输入

一.输出:C++还提供了一些操纵符,可以直接嵌入到输入/输出语句中来实现I/O格式控制.在使用setprecision和setw操纵符时要在程序开头包含iomanip.h.

操纵符名含义

dec

数值数据采用十进制表示

hex

数值数据采用十六进制表示

oct

数值数据采用十进制表示

ws

提取空白字符

endl

插入换行符,并刷新流

ends插入空字符setprecision(int)

设置浮点数的小数位数(包括小数点)

setw(int)

设置域宽

1.

输出常数用cout可以显示数字和字符,可以输出常数.例.#include<iostream.h>voidmain(){intn=50;floatf=20.3;

cout<<"n="<<n<<endl;

cout<<"f="<<f<<endl;}

运行结果为:

n=0f=20.3000三个常用的控制符是hex,oct和dec,它们分别对应16进制数,8进制数和十进制数的显示.这三个控制符在iostream.h头文件中定义.

#include<iostream.h>voidmain(){intnumber=1001;

cout<<"decimal:"<<dec<<number<<endl<<"hexadecimal:"<<hex<<number<<endl<<"octal:"<<oct<<number<<endl;}

运行结果为:

decimal:1001hexadecimal:3e9octal:1751

2.输出八进制和十六进制数

3.设置值的输出宽度

除了使用空格来强行控制输出间隔外,还可以用setw(n)控制符.如果一个值需要比setw(n)确定的字符数更多的字符,则该值将使用它所需要的所有字符.例.Floatamount=3.14159;

cout<<setw(4)<<amount<<endl;

其运行结果为:3.14159.它并不按4位宽度,而是按实际宽度输出.如果一个值的字符数比setw(n)确定的字符数个数更少,则在数字字符前显示空白.不同于其他控制符,setw(n)仅仅影响下一个数值输出,换句话说,使用setw设置的间隔方式并不保留其效力.4.控制浮点数值显示使用setprecision(n)可控制输出流显示浮点数的数字个数.C++默认的流输出数值有效位为6.二.输入

当程序需要执行从键盘输入时,可以使用抽取操作符">>"从cin输入流中抽取字符.例.Int

myage;cin>>myage;

不管把什么基本数据类型的名字或值传给流,它都能懂.Cin可以调整行,自动识别变量位置和类型.它能够知道抽取变量的类型.

11.2.8函数参数的缺省在C++中函数可以使用缺省参数,例:voidPutHzxy(char*str,intx=-1,inty=-1){if(x==-1)x=wherex();if(y==-1)y=wherey();

moveto(x,y)

PutHz(str);}

可以有两种方式调用函数PutHzxy(),例如:

PutHzxy("C++语言");//使用缺省参数,在当前位置输出

PutHzxy("C++语言",10,10);//没有使用缺省参数

11.3C++程序结构

我们从最简单的程序例子来分析C++的程序组成。例:下面是一个完整的输出程序。

#include<iostream.h>voidmain(){cout<<"hello,world!"<<endl;}

运行结果为:hello,world!C++的程序结构由注释,编译预处理和程序主体组成.

一.注释注释是程序员为读者作的说明,是提高程序可读性的一种手段.二.编译预处理每个以符号“#”开头的行,称为编译预处理行.如“#include”称为文件包含预处理命令.编译预处理是C++组织程序的工具.三.程序主体main()表示主函数,每一个C++程序都必须有一个main()函数.Main()作为程序的入口.Main()前面的void表示该main()函数没有返回值.函数体用花括号{

}括起来.描述一个函数所执行算法的过程称为函数定义.例如,这里的main()函数头和函数体构成了一个完整的函数定义.例如,下面的程序求一个表达式的值.#include<iostream.h>voidmain(){inta,b,result;

cout<<"pleaseinputtwonumber:\n";

cin>>a>>b;result=3*a-2*b+1;

cout<<"resultis"<<result<<endl;}运行结果为:

pleaseinputtwonumber:8612resultis235

11.4面向对象的程序设计的重要特征

11.4.1类

类是一种复杂的数据类型,构成了实现C++面向对象程序设计的基础,它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体。因此,在面向对象中类具有更高的抽象性,类中的数据具有隐藏性,类还具有封装性(Inheritance)。类是面向对象程序设计的核心,它实际上是一种新的数据类型,也是抽象类型的工具,因为类是通过抽象数据类型的方法来实现的一种新的数据类型。类是对某一类对象的抽象。类的定义类(Class)是C++的精华,是进行封装和数据隐藏的工具。这是面向对象程序设计的一个重要机制。封装是描述把一个数据结构同操作数据的函数衔接在一起构成一个具有类类型的对象的术语。在C++中,封装借助于类来达到的。封装要求一个对象应具备明确功能,并有一个接口以便和其它对象相互作用。函数是将逻辑上有关的语句和数据集合在一起,主要用于执行;而类则是逻辑上有关的函数及其数据的集合,它主要不是用于执行,而是提供所需要的资源。在使用一个类之前必须先定义类。定义一个类的语法格式如下所示:class<类名>{private:<私有成员数据及函数;>protected:<保护成员数据及函数;>public:<公共成员数据及函数;>};

其中,class是定义类的关键字。<类名>是一种标识符,一对花括号内是说明部分(包括前面的类头)说明该类的成员。类的成员包含数据成员和成员函数两部分。一个类含有私有(private)成员、保护成员(protected)和公有成员(public)三部分。它们在类体内(即一队花括号内)出现的先后顺序无关,并且允许多次出现,用它们来说明类成员的访问权限。默认时在类中定义的项都是私有的。私有变量和函数只能被该类本身的成员函数存取或调用;保护成员除可以被本类中的成员函数访问外,还可以被本类派生的类的成员函数访问,因此用于类的继承;公有成员可以被本类以外的函数访问,是类与外部的接口。

类是面向对象程序设计最基本的单元,在设计面向对象程序时,首先要以类的方式描述实际待解决的问题,也就是将问题所要处理的数据定义成类的私有或公共类型的数据,同时将处理问题的方法定义成类的私有或公有的成员函数。其中,<各个成员函数的实现>是类定义中的实现部分,这部分包含所有在类体内说明的函数的定义。如果一个成员函数在类体内定义了,实现部分将不出现。如果所有的成员函数都在类体内定义,则实现部分可以省略。例如,下面给出一个关于日期的类的定义,该类的对象将是某一个具体的日期。classTDate{private:

intyear,month,day;public:int

IsLeapYear();voidPrint();};定义类时的注意事项在类体中不允许对所定义的数据成员进行初始化。类中的数据成员类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是对象。当一个类的对象作为这个类的成员时,如果另一个类的定义在后,需要提前说明。一般,在类体先说明公有成员,它们是用户不感兴趣的。在说明数据成员时,一般按数据成员的类型大小,由小到大说明,这样可提高时空利用率。经常习惯地将类定义的说明部分或者整个定义部分(包含实现部分)放到一个头文件中。11.4.2对象在C++中,对象是声明为类类型的一个数据项,是类的实际变量。程序员也可以定义类的变量。这个定义的类的变量在C++中就被称为对象。对象有时也称为类的实例(Instance)。由此可见,类是程序中的一个静态的概念,而对象是程序中的一个动态的概念。对象是类的实例。对象是属于某个已知的类。在创建对象中,类被用作模板,类和对象的关系就如同整型int与整型变量之间的关系。因此,定义对象之前,一定要先定义好该对象的类。对象的定义在C++中有两种方法可以定义类的对象:第一种是在定义好类后,再定义类的对象,也是最常用的一种对象的定义方法,其一般格式如下:类名对象1[,对象2,...];

例如:TDatedate1,data2;

其中,Tdate

为日期类的类名,date1和date2是一般的对象名。除此之外,还可以是指向对象的指针或引用名,也可以是对象数组名。当有多个对象名时,多个对象名之间有逗号分隔。例如:Tdate*Pdate,data[31];

还有一种是在定义类的同时直接定义类的对象,即在定义类的右大括号“}”后直接写出属于该类的对象名表列,即:

class类名

{

成员变量表列;

成员函数表列;}对象名表列;对象成员的表示方法一个对象的成员就是该对象的类所定义的成员。对象成员有数据成员和成员函数。一般对象的成员表示如下:<对象名>.<成员名>或者<对象名>.<成员名>(<参数表>)前者用来表示数据成员的,后者用来表示成员函数的。例如,date1的成员表示为:

date1.year,date1.month,date1.day

分别表示Tdate类的date1对象的year成员,month成员和day成员。

Date1.SetDate(inty,intm,intd)

表示Tdate类的date1对象的成员函数SetDate()。

这里,.是一个运算符,该运算符的功能是表示对象的成员,用法同上。

指向对象的指针的成员表示如下:

<对象指针名>-><成员名>

或者

<对象指针名>-><成员名>(<参数表>)

这里的->是一个表示成员的运算符,它用来表示指向对象的指针的成员。下面的两种表示是等价的:

<对象指针名>-><成员名>与(*<对象指针名>).<成员名>这对于成员函数也适用。

由同一个类所创建的对象的数据结构是相同的,类中的成员函数是共享的。两个不同的对象的名字是不同的,它们的数据结构的内容(即数据成员的值)是不同的。因此,系统对已经定义的对象仅仅给它分配数据成员变量,而一般数据成员又都为私有成员,不同对象的数据成员的值可以是不同的。例如:分析下列程序的输出结果。#include<iostream.h>#include"tdate.h"voidmain(){Tdatedate1,date2;date1.SetDate(1996,9,1);date2.SetDate(1998,10,10);cout<<leap<<endl;date1.Print();date2.Print();}执行该程序后,输出结果如下:11996.9.11998.10.10

该程序的主函数中,定义了两个对象date1和date2,并通过成员函数SetDate()个对象date1和date2赋值。程序中,通过成员函数IsLeapYear()判断对象date1的年份(1996)是否是闰年,本例输出为1表示1996年是闰年。最后,通过调用成员函数Print()输出显示对象date1和date2的数据成员的值,即年、月和日。11.4.3构造函数和析构函数对象的意义表达了现实世界的实体,因此,一旦建立对象,必须有一个有意义的初始值。C++规定与类同名的成员函数是构造函数。建立和初始化对象的过程专门由该类的构造函数来完成。构造函数的功能是在创建对象时,使用给定的值来将对象初始化。这个构造函数很特殊,只要对象建立,它马上被调用,给对象分配空间和初始化。C++另有一种析构函数,它也是类的成员函数,它的功能是用来释放一个对象的。在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。例如,一张桌子要扔掉,必须将桌子里面的东西拿来这些东西可能有用,不能随捉系一起扔。类似这些事就由析构函数来完成。构造函数的特点如下:构造函数是成员函数,函数体可写在类体内,也可以写在类体外。构造函数是一个特殊的函数,该函数的名字与类相同,该函数不指定类型说明,它有隐含的返回值,该值由系统内部使用。该函数可以有一个参数,也可以有多个参数。构造函数可以重载,即可以定义多个参数个数不同的函数。程序中不能直接调用构造函数,在创建对象时系统自动调用构造函数。析构函数的特点如下:析构函数是成员函数,函数体可以写在类体内,也可以写在类体外。析构函数也是一个特殊的函数,它的名字同类名,并在前面加“~”字符,用来与构造函数加以区别。析构函数不指定数据类型,并且没没有参数。一个类中只可能定义一个析构函数。析构函数可以被调用,也可以调用。两种情况下,析构函数被自动调用。若一个对象被定义在一个函数体内,则当这个函数结束时,该对象的析构函数被自动调用;当一个对象用new运算符被动态创建,在用delete运算符释放它时,delete会自动调用析构函数。

在类定义时没有定义任何构造函数时,则编译器自动生成一个不带参数的缺省构造函数,其格式如下:<类名>::<缺省构造函数名>(){}

按构造函数的规定,缺省构造函数名同类名。缺省构造函数的怎样格式也可以由程序定义在类体中。在程序中定义一个对象而没有指明初始化时,则编译器便按缺省构造函数来初始化该对象。

用缺省构造函数对对象初始化时,则将对象的所有数据成员都初始化为零或空。同理,如果一个类中没有定义析构函数时,则编译系统也生成一个称为缺省析构函数,其格式如下:<类名>::~<缺省析构函数名>{}<缺省析构函数名>即为该类的类名。缺省析构函数是一个空函数。11.4.4继承性继承是面向对象程序设计中最重要的机制。这种机制改变了过去传统的非面向对象程序设计中那种对不适合要求的用户定义数据类型进行改写甚至重写的法克服了传统程序设计方法对编写出来的程序无法重复利用程序资源的浪费的缺点。面向对象程序设计的继承机制给我们提供了无限重复利用程序资源的一种途径。

通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称父类。由已存在的类派生出的新类称为派生类,又称为子类。

在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生第一张幻灯片的继承称为多继承。单继承形成了类的层次,如图(a)和(b)所示。ABCXYZ(a)单继承(b)多继承派生类的定义格式:单继承的定义格式如下:

class<派生类名>:<继承方式><基类名>{<派生类新定义成员>};其中,<派生类名>是新定义的一个类的名字,它是从<基类名>中派生的,并且按指定的<继承方式>派生的。<继承方式>常使用如下三种关键字给予表示:

public表示公有基类;

private表示私有基类;

protected表示保护基类。多继承的定义格式如下:

class<派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…{<派生类新定义的成员>};

派生类的三种继承方式公有继承(public)、私有继承(private)和保护继承(protected)是常用的三种继承方式。1.公有继承(public)

公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。2.私有继承(private)

私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。3.保护继承(protected)

保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元所访问,基类的私有成员仍然是私有的。将上述三种不同继承方式的基类特性与派生类特性见表11.5。

继承方式基类特性派生类特性公有继承publicprotectedprivatepublicprotected不可访问私有继承publicprotectedprivateprivateprivate不可访问保护继承publicprotectedprivateprotectedprotected不可访问对于公有继承方式:(1)基类成员对其对象的可见性:公有成员可见,其他不可见。这里保护成员同于私有成员。(2)基类成员对派生类的可见性:公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。(3)基类成员对派生类对象的可见性:公有成员可见,其他成员不可见。对于私有继承方式:(1)基类成员对其对象的可见性:公有成员可见,其他成员是不可见。(2)基类成员对派生类的可见性:公有成员和保护成员是可见的,而私有成员是不可见的。基类成员对派生类对象的可见性:所有成员都是不可见的。对于保护继承方式:该继承方式与私有继承方式的情况相同。两者区别仅在于对派生类成员而言,对基类成员有不同的可见性。11.4.5作用域运算符类的方法的具体实现和普通函数的具体实现只是在函数的头部有略微不同的格式。一般来说,如果类的方定义是在类的外部实现的,则在定义方法时必须把类名放在方法名之前,中间用作用域运算符(“::”)隔开,其一般形式如下所示:类名::方法名

这样,即使几个类中的方法名相同,也可以用这种形式把它们区分开来。和普通函数一样,类的方法也应该既有返回值类型,也有参数表列(当然也可以没有参数)。一个方法的头部各部分如下所示:访问控制:函数返回值函数名(参数表列);

运算符::用来连接类名和成员名,以告知编译程序这个成员属于哪个类。但作用域运算符还有其它的用途:它允许在一个封闭的作用域里村区与局部说明相同的名字。例如:inti;//全局变量voidf(){inti;//局部变量i=10;//使用局部变量}

但是,如果函数f()要存取全局变量i,只需要将运算符::置于i之前即可。如下所示:inti;//全局变量voidf(){inti;//局部变量::i=10;//全局变量}11.4.6动态内存分配在C语言里,动态内存分配是通过使用函数malloc()和free()实现的。为

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论