第 11章 C++的面向对象基础知识第 11章 C++的面向对象基础知识
11.1 面向对象的程序设计概述
11.2 C++对 C的扩充
11.3 C++程序结构
11.4 面向对象程序设计的特征
11.5 小结第 11章 C++的面向对象基础知识
11.1 传统的程序设计方法一.程序设计方法的进步在 20世纪 60年代,软件曾出现过严重危机,由软件错误而引起的信息丢失、系统报废事件屡有发生。为此 1968年,荷兰学者提出了程序设计中常用的 GOTO语句的三大危害:破坏了程序的静动一致性;程序不易测试;限制代码化。此举引起了软件界长达数年的论战,并由此产生了结构化程设计方法,同时诞生了基于这一设计方法的程序设计 Pascal.Pascal一经推出,
它的简洁明了以及丰富的数据结构和控制结构,为程序员提供了极大的方便性与灵活性,同时它特别适合计算机系统,因此大受欢迎。结构化程序设计思想在整个 20世纪 70的软件开发中占绝对统治地位。
第 11章 C++的面向对象基础知识二,什么是结构化程序设计 (Structure Programming)
结构化程序设计是上个世纪 60年代诞生的,在 70年代到
80年代已遍及全球,结构化程序设计的设计思路是:自顶向下,逐步求精;其程序结构是按功能划分若干个基本模块,这些模块形成一个树状结构;各模块之间的关系尽可能简单,在功能上相对独立;每一模块内部均是由顺序,选择和循环三种基本结构组成; 结构化程序设计方法的四条原则是,1,自顶向下; 2,逐步求精; 3.
模块化; 4,限 制 使 用 g o t o 语句 。
第 11章 C++的面向对象基础知识当数据和过程相互独立时,总存在着用错误的数据调用正确的程序模块或用正确的数据调用了错误的程序模块的可能性。因此,要使数据与程序始终保持相容,已经成为程序员的一个沉重负担。上述这些问题,结构化程序设计方法本身是解决不了的,
到了 70年代末期,结构化程序设计语言和结构化分析与设计已无法满足用户需求的变化,于是面向对象技术开始浮出水面。
第 11章 C++的面向对象基础知识
11.1.2面向对象的程序设计方法一.面向对象的由来和发展面向对象方法起源于面向对象语言,编程语言得到应用和发展的同时,面向对象的方法得到了发展 。和任何事物一样,面向对象语言也经历了它的发生、发展阶段,走向成熟。
1.在 60年代初期,Algo语言使封装思想诞生 。
2.在 60年代后期,Simula引入对象和消息机制,对象和对象之间可以通过发送消息来进行相互通信,这就是导致了数据封装与通信思想的产生。
第 11章 C++的面向对象基础知识
3.到了 70年代,都许多语言如 CLU,Ads,Modula-2等都开始支持数据与封装,这导致了抽象数据类型发展。
4.1980年,出现 Smalltalk-80商品化的面向对象语言,
它是纯粹的面向对象编程语言。
5.80年代中期到 90年代,出现了大批面向对象语言,
面向对象语言趋于成熟,从此面向对象方法走向实用。
二.面向对象的基本思想其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。
第 11章 C++的面向对象基础知识三.面向对象的基本概念
1.对象:特性 +行为第一个面向对象的程序设计语言是 60年代开发的 Simula—
67。其目的是为了解决模拟问题。典型的模拟问题是银行出纳业务,包括出纳部门、顾客、业务、货币的单位等大量的
“对象”。把那些在程序执行期间除了状态之外其他方面都一样的对象归在一起,构成对象的“类”,这就是“类”一词的来源。类描述了一组有相同特性(数据元素)和相同行为(函数)的对象。
2.继承:类型关系特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。
第 11章 C++的面向对象基础知识一个 类可以是多个一般类的特殊类,它从多个一般类中继承了 属性与服务,这称为多继承。例如,客轮是轮船和客运工 具的特殊类。在 java语言中,通常我们称一般类为父类,特 殊类为子类。
3.封装性封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义:
把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界,只保留有限的对外接口使之与外部发生联系。
4,多态性对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。
第 11章 C++的面向对象基础知识
11.2 C++对 C的扩充
11.2.1 C++语言源程序的编译为了解 C++语言源程序的编译过程首先介绍一些基本术语:
1.源程序:用源语言写的有待翻译的程序,称为“源程序”。 源程序可以是汇编语言,也可以是高级程序设计语言,
所以用它们写出的程序都是源程序。
2.目标程序:是源程序通过翻译加工以后所生成的程序。
目标程序可以用机器语言表示,也可以用汇编语言或其他中间语言表示。
3.翻译程序:是指用来把源程序翻译为目标程序的程序。
对翻译程序来说,源程序是它的输入,而目标程序则是其输出。
第 11章 C++的面向对象基础知识
11.2.2基本数据类型
1,C++类型分类
C++的数据类型有基本数据类型和非基本数据类型。基本数据类型是 C++内部预先定义的数据类型。主要有整型、
字符型、实型、布尔型这四种基本类型。非基本数据类型包括指针、数组、结构、类等。
2.整型标准 C++中 6种整型 short,int,long,unsigned short、
unsigned int,unsigned long。以在十六位计算机中表示为例它们的范围如下表 11.2-1:
第 11章 C++的面向对象基础知识类型 说明 长度(字节) 范围
short 短整型 2 -32768~32767
int 整型 2 -32768~32767l
long 长整型 4- 2147483648~21474
83647
unsigned
short
无符号短整型
2 0~65535
unsigned int 无符号整型 2 0~65535
unsigned
long
无符号长整型
4 0~4294967295
第 11章 C++的面向对象基础知识
3.字符型字符文字由单引号‘限定,字符值以整型的方式存储。
【 例 11.1】 字符变量
int main()
{//打印字符和已在内部存储的整型值
char c=ˊ Aˊ ;
cout <<"c="<<c<<",int(c)="<<int(c)<<endl;
c=ˊ tˊ ;
cout<<"c="<<c<<",int(c)="<<int(c)<<endl;
}
第 11章 C++的面向对象基础知识运行结果:
c=A,int(c)=65
c=t,int(c)=116
由于字符值被用于输入和输出,因此它们表现为字符的形式而不是整型的形式:字符 A是以字母 A的形式而不是以它的内部表示的整数值 65的形式被打印出来。程序中用类型转换运算符 int()将其内部对应的整型值展示出来。这就是字母的 ASCII码。字符型的范围如下表 11.2-2:
类型 说明 长度(字节) 范围
char 字符型 1 -128~127
unsigned char 无符号字符型
1 0~255
第 11章 C++的面向对象基础知识
4.实型
C++支持 3种实数型,float,double,long double。在大多数系统中,double使用 float两倍的字节数。典型的是 float
使用 4字节,double使用 8字节,long double使用 8,10,12
或 16字节。实型的范围如下表 11.2-3:
类型 说明 长度(字节)
float 浮点型 4
double 双精度型 8
Long double 长双精度型 10
第 11章 C++的面向对象基础知识
5.布尔型布尔型变量只能取两个值,false和 true。这两个值被存为 0和 1。
标准 C++中,布尔型被称为 bool。
【 例 11.3】 布尔类型变量
int main()
{//打印布尔变量的值
bool flag=false;
cout<<"flag="<<flag<<endl;
flag=true;
cout<<"flag="<<flag<<endl;
}
第 11章 C++的面向对象基础知识运行结果:
flag=0
flag=1
注意 false值被打印成整数 0而 true值被打印成整数 1。
6.数据类型转换
c++中数据类型转换有两种,即隐式类型转换和显式类型 转换。 隐式类型转换 由编译器自动完成,当编译器遇到不同类型的数据参与同一运算时,会自动将它们转换成相同类型后在进行运算。隐式类型转换按从低到高的顺序进行。 显式类型转换它是程序员显式指出的类型转换,转换形式有两种,〈 类型名 〉
(表达式)( 〈 类型名 〉 ) 表达式通过类型的显式转换可以将“表达式”转换成适当的类型。
第 11章 C++的面向对象基础知识
11.2.3变量的定义变量名要遵守以下规则:
1) 不能是 C++保留字 。
2)第一个字符必须是字母或下划线。
3)中间不能有空格。
变量就是值可变的量,每个变量由一个变量名唯一标识,同时,每个变量又具有一个特定的数据类型。
类型标志着这个变量将来的用法以及它将保存哪种类型的数据值。
1.命名变量名第 11章 C++的面向对象基础知识可以在一个语句里建立多个同一类型的变量,方法是在类型后写上多个变量名,中间用逗开。例如:
unsigned myage,myweight;
long area,width,length;
在同一语句里不能混合定义不同类型的变量
3.变量赋值与初始化用赋值运算符,=”给变量赋值。
例如,int depth; depth=5;
也可在定义时直接给变量赋值。在定义的同时,赋给变量一个初始值,称为变量的初始化。例如,int depth=5; //初始化第 11章 C++的面向对象基础知识在定义时也可以初始化多个变量。例如,int depth=5,
length=6;不是所有的变量在定义时都需要初始化。例如:
double area,radius=15; 该变量定义并不是将 15同时赋给这两个变量,而是变量 radius初始化为 15,area只是定义,没有被初始化。
4.用 typedef定义自己的变量类型在 C++中可以利用 typedef定义自己的变量类型,其形式为,typedef〈 类型说明 〉 ; 〈 类型说明 〉 类似于变量说明,只是变量名用类型名代替了,实际上,这等于定义了一个同义词,
这种方式与创建一个新的类型是不同的。 Typedef没有实际地定义一个新的数据类型,在建立一个 typedef类型时没有分配内存空间。例如:
第 11章 C++的面向对象基础知识
typedef int depth;
typedef char string[8];
使用自定义类型有几点好处:一是可以更好地表达程序员的意思,如用 depth来表示将要定义的标识符是属于深度一类的数据,用 string表示程序员想要定义的是一个字符串,这比直接用系统预定义的类型清晰得多;二是简单方便,一些数据类型可以用简单的类型标识符来表示,不用每次都麻烦地写复杂的定义。
第 11章 C++的面向对象基础知识
1,4,4 C++的函数原型函数原型是一条程序语句,它由函数返回类型 ﹑ 函数名和参数表构成,形式为:返回类型 函数名(参数表);
在 C++中,函数声明就是函数原型。在 C++中,函数的声明可以在主程序以前,也可以在主程序之後。程序:使用函数 C++版本(函数的声明在主程序以前)
如果函数在主程序之后声明,在主程序以前必須有一個叫做 函数原型 的語句。函数原型告訴 C++ 編譯程序参数的数据類型、参数的数目及函数回传的数据類型,這些資料必須和函数的声明一致。
第 11章 C++的面向对象基础知识在数据原型中,参数名称是不需要的,就算有也不一定要和函数声明的一样。例如,函数原型
float power(float base,int n);
可以寫成
float power(float,int);
第 11章 C++的面向对象基础知识
11.2.5 常量说明一,常类型 const
常数型是指使用类型修饰符 const说明的类型,常类型的变量或对象的值是不能被更新的。因此,定义或说明常类型时必须进行初始化.
二.常量分类
1.一般常量
2.常对象
3.常指针第 11章 C++的面向对象基础知识
1.一般常量一般常量是指简单类型的常量。
定义或说明一个常数组可采用如下格式:
<类型说明符 > const <数组名 >[大小 ]
或者 const <类型说明符 > <数组名 >[大小 ]
例如,int const a[5]={1,2,3,4,5};
第 11章 C++的面向对象基础知识
2.常对象常对象是指对象常量,定义格式如下:
<类名 > const <对象名 >
或者 const <类名 > <对象名 >
定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符 const可以放在类名后面,也可以放在类名前面,
第 11章 C++的面向对象基础知识
3.常指针下面定义的一个指向字符串的常量指针:
char * const prt1 =stringprt1;
其中,ptr1是一个常量指针,
下面赋值是非法的,ptr1=stringprt2;
而下面的赋值是合法的,*ptr1="m";
因为指针 ptr1所指向的变量是可以更新的,不可更新的是常量指针 ptr1所指的方向 (别的字符串 ).
第 11章 C++的面向对象基础知识
11.2.6 C++的注释语句一,什么是注释注释是程序员为读者作的说明,是提高程序可读性的一种手段,
一般可将其分为两种:序言注释和注解性注释,前者用于程序开头,说明程序或文件的名称,用途,编写时间,编写人及输入输出说明等,后者用于程序中难懂的地方,
第 11章 C++的面向对象基础知识二,二,注释的书写
1,C++风格的注释为" //"之后的内容,直到换行,注释仅供阅读程序使用,是程序的可选部分,在生成可执行程序之前,C++忽略注释,并把每个注释都视为一个空格,
2,另外,C++还兼容了C语言风格的注释,是指符号" /*"与" */"之间的任何字符串,这些字符可以跨过多行,
第 11章 C++的面向对象基础知识
11.2.7 C++的标准 I/O操作所有用到标准输入输出的C++程序都必须包含
iostream这个预处理伪指令,标识符 iostream是标准
C++库中一个文件的名字,格式 为,include
<iostream.h>,iostream.h是系统定义的一个头文件,
它设置了C++的 I/O相关环境,定义输入输出流对象 cout与 cin等,
一,输出二,输入第 11章 C++的面向对象基础知识一.输出,C++还提供了一些操纵符,可以直接嵌入到输入
/输出语句中来实现I/O格式控制.在使用 setprecision和
setw操纵符时要在程序开头包含 iomanip.h.
操纵符名 含义
dec 数值数据采用十进制表示
hex 数值数据采用十六进制表示
oct 数值数据采用十进制表示
ws 提取空白字符
endl 插入换行符,并刷新流
ends 插入空字符
setprecision(int) 设置浮点数的小数位数 ( 包括小数点 )
setw(int) 设置域宽第 11章 C++的面向对象基础知识
1,输出常数用 cout可以显示数字和字符,可以输出常数,
例,#include <iostream.h>
void main( )
{ int n=50;
float f=20.3;
cout<<"n="<<n<<endl;
cout<<"f="<<f<<endl;}
运行结果为:
n=0
f=20.3000
第 11章 C++的面向对象基础知识三个常用的控制符是 hex,oct和 dec,它们分别对应16进制数,
8进制数和十进制数的显示,这三个控制符在 iostream.h头文件中定义,
#include <iostream.h>
void main( )
{int number=1001;
cout<<"decimal:"<<dec<<number<<endl
<<"hexadecimal:"<<hex<<number<<endl
<<"octal:"<<oct<<number<<endl;}
运行结果为:
decimal:1001
hexadecimal:3e9
octal:1751
2,输 出 八 进 制 和 十 六 进 制 数第 11章 C++的面向对象基础知识
3.设置值的输出宽度除了使用空格来强行控制输出间隔外,还可以用 setw(n)
控制符,如果一个值需要比 setw(n)确定的字符数更多的字符,则该值将使用它所需要的所有字符,
例,Float amount=3.14159;
cout<<setw(4)<<amount<<endl;
其运行结果为:3,14159,它并不按4位宽度,而是按实际宽度输出,如果一个值的字符数比 setw(n)确定的字符数个数更少,则在数字字符前显示空白,不同于其他控制符,setw(n)仅仅影响下一个数值输出,换句话说,使用 setw设置的间隔方式并不保留其效力,
第 11章 C++的面向对象基础知识
4,控制浮点数值显示使用 setprecision(n)可控制输出流显示浮点数的数字个数,C++默认的流输出数值有效位为6,
第 11章 C++的面向对象基础知识二.输入当程序需要执行从键盘输入时,可以使用抽取操作符" >>"从 cin输入流中抽取字符,
例,Int myage;
cin>>myage;
不管把什么基本数据类型的名字或值传给流,它都能懂,Cin可以调整行,自动识别变量位置和类型,它能够知道抽取变量的类型,
第 11章 C++的面向对象基础知识
11.2.8 函数参数的缺省在 C++中函数可以使用缺省参数,例:
void PutHzxy(char *str,int x=-1,int y=-1)
{ if (x==-1) x=wherex();
if (y==-1) y=wherey();
moveto(x,y)
PutHz(str);}
可以有两种方式调用函数 PutHzxy( ),例如:
PutHzxy("C++语言 ");//使用缺省参数,在当前位置输出
PutHzxy("C++语言 ",10,10);//没有使用缺省参数第 11章 C++的面向对象基础知识
11.3 C++程序结构我们从最简单的程序例子来分析 C++的程序组成。
例:下面是一个完整的输出程序 。
#include<iostream.h>
void main( )
{cout<<"hello,world!"<<endl;}
运行结果为,hello,world!
C++的程序结构由注释,编译预处理和程序主体组成,
第 11章 C++的面向对象基础知识一,注释注释是程序员为读者作的说明,是提高程序可读性的一种手段,
二,编译预处理每个以符号,#,开头的行,称为编译预处理行,如,#include”
称为文件包含预处理命令,编译预处理是C ++组织程序的工具,
三,程序主体
main( )表示主函数,每一个 C++程序都必须有一个 main( )函数,Main( )作为程序的入口,Main( )前面的 void表示该 main( )
函数没有返回值,函数体用花括号 { }括起来,描述一个函数所执行算法的过程称为函数定义,例如,这里的 main( )函数头和函数体构成了一个完整的函数定义,
第 11章 C++的面向对象基础知识例如,下面的程序求一个表达式的值,
#include<iostream.h>
void main( )
{int a,b,result;
cout<<"please input two number:\n";
cin>>a>>b;
result=3*a-2*b+1;
cout<<"result is "<<result<<endl;
}
运行结果为:
please input two number:
86 12
result is 235
第 11章 C++的面向对象基础知识
11.4 面向对象的程序设计的重要特征
11.4.1 类类是一种复杂的数据类型,构成了实现 C++面向对象程序设计的基础,它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体 。 因此,在面向对象中类具有更高的抽象性,类中的数据具有隐藏性,类还具有封装性 (Inheritance)。 类是面向对象程序设计的核心,
它实际上是一种新的数据类型,也是抽象类型的工具,
因为类是通过抽象数据类型的方法来实现的一种新的数据类型 。 类是对某一类对象的抽象 。
第 11章 C++的面向对象基础知识类的定义类 (Class)是 C++的精华,是进行封装和数据隐藏的工具。这是面向对象程序设计的一个 重要机制。封装是描述把一个数据结构同操作数据的函数衔接在一起构成一个具有类类型的对象的术语。在 C++中,封装借助于类来达到的。封装要求一个对象应具备明确功能,并有一个接口以便和其它对象相互作用。函数是将逻辑上有关的语句和数据集合在一起,主要用于执行;而类则是逻辑上有关的函数及其数据的集合,它主要不是用于执行,而是提供所需要的资源。在使用一个类之前必须先定义类 。
第 11章 C++的面向对象基础知识定义一个类的语法格式如下所示:
class <类名 >
{
private:
<私有成员数据及函数 ;>
protected:
<保护成员数据及函数 ;>
public:
<公共成员数据及函数 ;>
};
第 11章 C++的面向对象基础知识其中,class是定义类的关键字。 <类名 >是一种标识符,
一对花括号内是说明部分(包括前面的类头)说明该类的成员。类的成员包含数据成员和成员函数两部分。一个类含有私有 (private)成员、保护成员 (protected)和公有成员
(public)三部分。它们在类体内(即一队花括号内)出现的先后顺序无关,并且允许多次出现,用它们来说明类成员的访问权限。默认时在类中定义的项都是私有的。私有变量和函数只能被该类本身的成员函数存取或调用;保护成员除可以被本类中的成员函数访问外,还可以被本类派生的类的成员函数访问,因此用于类的继承;公有成员可以被本类以外的函数访问,是类与外部的接口。
第 11章 C++的面向对象基础知识类是面向对象程序设计最基本的单元,在设计面向对象程序时,首先要以类的方式描述实际待解决的问题,也就是将问题所要处理的数据定义成类的私有或公共类型的数据,同时将处理问题的方法定义成类的私有或公有的成员函数。其中,<各个成员函数的实现 >是类定义中的实现部分,这部分包含所有在类体内说明的函数的定义。如果一个成员函数在类体内定义了,实现部分将不出现。如果所有的成员函数都在类体内定义,则实现部分可以省略。
第 11章 C++的面向对象基础知识例如,下面给出一个关于日期的类的定义,该类的对象将是某一个具体的日期。
class TDate
{
private:
int year,month,day;
public:
int IsLeapYear();
void Print();
};
第 11章 C++的面向对象基础知识定义类时的注意事项
在类体中不允许对所定义的数据成员进行初始化 。
类中的数据成员类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是对象。
当一个类的对象作为这个类的成员时,如果另一个类的定义在后,需要提前说明。
一般,在类体先说明公有成员,它们是用户不感兴趣的。在说明数据成员时,一般按数据成员的类型大小,
由小到大说明,这样可提高时空利用率。
经常习惯地将类定义的说明部分或者整个定义部分
(包含实现部分)放到一个头文件中。
第 11章 C++的面向对象基础知识
11.4.2 对象在 C++中,对象是声明为类类型的一个数据项,
是类的实际变量 。 程序员也可以定义类的变量 。 这个定义的类的变量在 C++中就被称为对象 。 对象有时也称为类的实例 (Instance)。 由此可见,类是程序中的一个静态的概念,而对象是程序中的一个动态的概念 。
对象是类的实例 。 对象是属于某个已知的类 。 在创建对象中,类被用作模板,类和对象的关系就如同整型
int与整型变量之间的关系 。 因此,定义对象之前,一定要先定义好该对象的类 。
第 11章 C++的面向对象基础知识对象的定义在 C++中有两种方法可以定义类的对象:第一种是在定义好类后,再定义类的对象,也是最常用的一种对象的定义方法,其一般格式如下:
类名 对象 1[,对象 2,...];
例如,TDate date1,data2;
其中,Tdate 为日期类的类名,date1和 date2是一般的对象名。除此之外,还可以是指向对象的指针或引用名,也可以是对象数组名。当有多个对象名时,
多个对象名之间有逗号分隔。
例如,Tdate*Pdate,data[31];
第 11章 C++的面向对象基础知识还有一种是在定义类的同时直接定义类的对象,即在定义类的右大括号,}”后直接写出属于该类的对象名表列,即:
class 类名
{
成员变量表列 ;
成员函数表列 ;
}对象名表列 ;
第 11章 C++的面向对象基础知识对象成员的表示方法一个对象的成员就是该对象的类所定义的成员。对象成员有数据成员和成员函数。
一般对象的成员表示如下:
<对象名 >.<成员名 >
或者
<对象名 >.<成员名 >(<参数表 >)
前者用来表示数据成员的,后者用来表示成员函数的。
第 11章 C++的面向对象基础知识例如,date1的成员表示为:
date1.year,date1.month,date1.day
分别表示 Tdate类的 date1对象的 year成员,month成员 和 day成员。
Date1.SetDate(int y,int m,int d)
表示 Tdate类的 date1对象的成员函数 SetDate()。
这里,.是一个运算符,该运算符的功能是表示对象的成员,用法同上。
第 11章 C++的面向对象基础知识指向对象的指针的成员表示如下:
<对象指针名 >-><成员名 >
或者
<对象指针名 >-><成员名 >(<参数表 >)
这里的 ->是一个表示成员的运算符,它用来表示指向对象的指针的成员。下面的两种表示是等价的:
<对象指针名 >-><成员名 > 与 (*<对象指针名 >).<成员名 >
这对于成员函数也适用。
第 11章 C++的面向对象基础知识由同一个类所创建的对象的数据结构是相同的,类中的成员函数是共享的。两个不同的对象的名字是不同的,它们的数据结构的内容(即数据成员的值)是不同的。因此,系统对已经定义的对象仅仅给它分配数据成员变量,而一般数据成员又都为私有成员,不同对象的数据成员的值可以是不同的。
第 11章 C++的面向对象基础知识例如:分析下列程序的输出结果。
#include<iostream.h>
#include"tdate.h"
void main()
{
Tdate date1,date2;
date1.SetDate(1996,9,1);
date2.SetDate(1998,10,10);
cout<<leap<<endl;
date1.Print();
date2.Print();
}
第 11章 C++的面向对象基础知识执行该程序后,输出结果如下:
1
1996.9.1
1998.10.10
该程序的主函数中,定义了两个对象 date1和 date2,并通过成员函数 SetDate()个对象 date1和 date2赋值。程序中,通过成员函数 IsLeapYear()判断对象 date1的年份
(1996)是否是闰年,本例输出为 1表示 1996年是闰年。
最后,通过调用成员函数 Print()输出显示对象 date1和
date2的数据成员的值,即年、月和日。
第 11章 C++的面向对象基础知识
11.4.3 构造函数和析构函数对象的意义表达了现实世界的实体,因此,一旦建立对象,必须有一个有意义的初始值。 C++规定与类同名的成员函数是构造函数。建立和初始化对象的过程专门由该类的构造函数来完成。构造函数的功能是在创建对象时,使用给定的值来将对象初始化。这个构造函数很特殊,只要对象建立,它马上被调用,给对象分配空间和初始化。
第 11章 C++的面向对象基础知识
C++另有一种析构函数,它也是类的成员函数,它的功能是用来释放一个对象的。在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。
例如,一张桌子要扔掉,必须将桌子里面的东西拿来这些东西可能有用,不能随捉系一起扔。类似这些事就由析构函数来完成。
第 11章 C++的面向对象基础知识构造函数的特点如下:
构造函数是成员函数,函数体可写在类体内,也可以写在类体外。
构造函数是一个特殊的函数,该函数的名字与类相同,该函数不指定类型说明,它有隐含的返回值,
该值由系统内部使用。该函数可以有一个参数,也可以有多个参数。
构造函数可以重载,即可以定义多个参数个数不同的函数。
程序中不能直接调用构造函数,在创建对象时系统自动调用构造函数。
第 11章 C++的面向对象基础知识析构函数的特点如下:
析构函数是成员函数,函数体可以写在类体内,也可以写在类体外。
析构函数也是一个特殊的函数,它的名字同类名,并在前面加,~”字符,用来与构造函数加以区别。析构函数不指定数据类型,并且没没有参数。
一个类中只可能定义一个析构函数。
析构函数可以被调用,也可以调用。两种情况下,析构函数被自动调用。若一个对象被定义在一个函数体内,则当这个函数结束时,该对象的析构函数被自动调用;当一个对象用 new运算符被动态创建,在用
delete运算符释放它时,delete会自动调用析构函数。
第 11章 C++的面向对象基础知识在类定义时没有定义任何构造函数时,则编译器自动生成一个不带参数的缺省构造函数,其格式如下:
<类名 >::<缺省构造函数名 >()
{
}
按构造函数的规定,缺省构造函数名同类名。缺省构造函数的怎样格式也可以由程序定义在类体中。
在程序中定义一个对象而没有指明初始化时,则编译器便按缺省构造函数来初始化该对象。
第 11章 C++的面向对象基础知识用缺省构造函数对对象初始化时,则将对象的所有数据成员都初始化为零或空。
同理,如果一个类中没有定义析构函数时,则编译系统也生成一个称为缺省析构函数,其格式如下:
<类名 >::~<缺省析构函数名 >
{
}
<缺省析构函数名 >即为该类的类名。缺省析构函数是一个空函数。
第 11章 C++的面向对象基础知识
11.4.4 继承性继承是面向对象程序设计中最重要的机制 。 这种机制改变了过去传统的非面向对象程序设计中那种对不适合要求的用户定义数据类型进行改写甚至重写的法克服了传统程序设计方法对编写出来的程序无法重复利用程序资源的浪费的缺点 。 面向对象程序设计的继承机制给我们提供了无限重复利用程序资源的一种途径 。
第 11章 C++的面向对象基础知识通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称父类。由已存在的类派生出的新类称为派生类,又称为子类。
第 11章 C++的面向对象基础知识在 C++语言中,一个派生类可以从一个基类派生,
也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生 第一张幻灯片 的继承称为多继承。
单继承形成了类的层次,如图 (a)和 (b)所示。
A
B C
X Y
Z
(a) 单继承 (b) 多继承第 11章 C++的面向对象基础知识派生类的定义格式:
单继承的定义格式如下:
class<派生类名 >:<继承方式 ><基类名 >
{
<派生类新定义成员 >
};
其中,<派生类名 >是新定义的一个类的名字,它是从
<基类名 >中派生的,并且按指定的 <继承方式 >派生的。
第 11章 C++的面向对象基础知识
<继承方式 >常使用如下三种关键字给予表示:
public 表示公有基类;
private 表示私有基类;
protected 表示保护基类。
多继承的定义格式如下:
class <派生类名 >:<继承方式 1><基类名 1>,<继承方式
2><基类名 2>,…
{
<派生类新定义的成员 >
};
第 11章 C++的面向对象基础知识派生类的三种继承方式公有继承 (public)、私有继承
(private)和保护继承 (protected)是常用的三种继承方式。
1,公有继承 (public)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。
2,私有继承 (private)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
第 11章 C++的面向对象基础知识
3,保护继承 (protected)
保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元所访问,基类的私有成员仍然是私有的。将上述三种不同继承方式的基类特性与派生类特性见表 11.5。
第 11章 C++的面向对象基础知识继承方式 基类特性 派生类特性公有继承 public
protected
private
public
protected
不可访问私有继承 public
protected
private
private
private
不可访问保护继承 public
protected
private
protected
protected
不可访问第 11章 C++的面向对象基础知识对于公有继承方式:
(1) 基类成员对其对象的可见性:公有成员可见,其他不可见。这里保护成员同于私有成员。
(2) 基类成员对派生类的可见性:公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
(3) 基类成员对派生类对象的可见性:公有成员可见,其他成员不可见。
第 11章 C++的面向对象基础知识对于私有继承方式:
(1) 基类成员对其对象的可见性:公有成员可见,其他成员是不可见。
(2) 基类成员对派生类的可见性:公有成员和保护成员是可见的,而私有成员是不可见的。
(3) 基类成员对派生类对象的可见性:所有成员都是不可见的。
对于保护继承方式:
该继承方式与私有继承方式的情况相同。两者区别仅在于对派生类成员而言,对基类成员有不同的可见性。
第 11章 C++的面向对象基础知识
11.4.5 作用域运算符类的方法的具体实现和普通函数的具体实现只是在函数的头部有略微不同的格式。一般来说,如果类的方定义是在类的外部实现的,则在定义方法时必须把类名放在方法名之前,中间用作用域运算符(,::”)隔开,
其一般形式如下所示:
类名,:方法名第 11章 C++的面向对象基础知识这样,即使几个类中的方法名相同,也可以用这种形式把它们区分开来。和普通函数一样,类的方法也应该既有返回值类型,也有参数表列(当然也可以没有参数)。一个方法的头部各部分如下所示:
访问控制,函数返回值 函数名(参数表列) ;
第 11章 C++的面向对象基础知识运算符,:用来连接类名和成员名,以告知编译程序这个成员属于哪个类。但作用域运算符还有其它的用途:它允许在一个封闭的作用域里村区与局部说明相同的名字。例如:
int i; //全局变量
void f()
{
int i; //局部变量
i=10; //使用局部变量
}
第 11章 C++的面向对象基础知识但是,如果函数 f()要存取全局变量 i,只需要将运算符,:
置于 i之前即可。如下所示:
int i; //全局变量
void f()
{
int i; //局部变量
::i=10; //全局变量
}
第 11章 C++的面向对象基础知识
11.4.6 动态内存分配在 C语言里,动态内存分配是通过使用函数 malloc()和
free()实现的。为保持兼容性,C语言的动态内存分配函数仍然为 C++所有。但 C++提供了它自己的、可供选择的基于两个新的运算符 new和 delete的动态分配系统。 C++的动态分配方法有客观的优越性。
运算符 new返回分配的内存的指针,和 malloc()一样,
new从堆里分配内存。如果没有足够的内存满足分配要求,它就返回一个空( Null)指针。 Delete运算符释放
new分配的内存。
第 11章 C++的面向对象基础知识运算符 delete必须用于先前 new分配的有效指针,如果使用了未定义的其他任何类型的指针,就会带来严重问题,如:系统崩溃。
与 malloc()和 free()相比较,new自动分配足够的空间以容纳指定类型的对象,而且不用使用 sizeof运算符,由于容量是自动计算的,所以消除了这方面发生错误的可能性; new自动返回指定类型的指针,不需要显示强制 new
和 delete都可以重载,允许创建定制的分配系统。
第 11章 C++的面向对象基础知识
11.4.7 多态性
C++中允许子类的成员函数重载基类的成员函数。例如,基类和派生类中都定义了计算学费的成员函数:
class Student
{
public:
//….
float calcTuition()
{ //…}
};
第 11章 C++的面向对象基础知识
class GraduateStudent:public Student
{
public:
//…
float calcTuition()
{
//…
}
};
第 11章 C++的面向对象基础知识
void main()
{
Student s;
GtaduateStudent gs;
s.calcTuition(); //调用 Student::calcTuition()
gs.calcTuition(); //调用 GraduateStudent::calcTuition()
}
第 11章 C++的面向对象基础知识在派生类中重载了 calcTuition()成员函数,学生的学费计算与研究生的学费计算方法不同。学生对象 s调用其学费计算函数显然指的是 Student::calcTuition()成员,而研究生对象 gs调用其学费计算函数时,两个重载函数都在它自己可使用范围内,C++编译规定,gs.calcTuition()指的是
GraduateStudent::calcTuition()。若派生类没有定义其
calcTuition(),则 gs.calcTuition()才指的是基类
Student::calcTuition()。
第 11章 C++的面向对象基础知识
11.5 小结本章我们介绍了 C++的一些背景知识和特点,包括 C++
的一些词法符号,然后介绍了 C++的数据类型、变量说明和运算符,以及程序的结构。 C++是一种表达式语言,所有的操作都用表达式表示 。一个类具有数据成员,还员函数,通过成员函数可以对数据成员进行操作,并实它的功能。定义一个类后,可以把该类名作为一种数据类型,定义其“变量”(对象)。程序利用点操作符(,)
访问类的公共成员。
第 11章 C++的面向对象基础知识程序可以在类的外部或内部定义它的成员函数,在类的外部定义成员函数时,必须指出所属的类名,并用符
(,:)把类名和函数名连接起来。
类的成员,包括数据和函数,都可以被说明为公有、
保护或私有。公有成员可以在程序中任意被访问,而保护或私有成员只能被这个类的成员函数所访问。类是一种复杂的数据类型,它是抽象数据类型的实现,是数据和相关操作的封装体。
第 11章 C++的面向对象基础知识构造函数是一种用于创建对象的特殊成员函数,人们调用一个构造函数来为类对象分配空间,给它的数据成员赋初值,以及其它请求资源的工作。每个类对象都必须在构造函数中诞生,一个类可能拥有一个或多个构造函数,编译程序为了决定调用哪个构造函数,要把对象声明中使用的变元(实参)和构造函数的参数进行较该过程与普通重载函数和匹配函数调用的方法相同。
11.1 面向对象的程序设计概述
11.2 C++对 C的扩充
11.3 C++程序结构
11.4 面向对象程序设计的特征
11.5 小结第 11章 C++的面向对象基础知识
11.1 传统的程序设计方法一.程序设计方法的进步在 20世纪 60年代,软件曾出现过严重危机,由软件错误而引起的信息丢失、系统报废事件屡有发生。为此 1968年,荷兰学者提出了程序设计中常用的 GOTO语句的三大危害:破坏了程序的静动一致性;程序不易测试;限制代码化。此举引起了软件界长达数年的论战,并由此产生了结构化程设计方法,同时诞生了基于这一设计方法的程序设计 Pascal.Pascal一经推出,
它的简洁明了以及丰富的数据结构和控制结构,为程序员提供了极大的方便性与灵活性,同时它特别适合计算机系统,因此大受欢迎。结构化程序设计思想在整个 20世纪 70的软件开发中占绝对统治地位。
第 11章 C++的面向对象基础知识二,什么是结构化程序设计 (Structure Programming)
结构化程序设计是上个世纪 60年代诞生的,在 70年代到
80年代已遍及全球,结构化程序设计的设计思路是:自顶向下,逐步求精;其程序结构是按功能划分若干个基本模块,这些模块形成一个树状结构;各模块之间的关系尽可能简单,在功能上相对独立;每一模块内部均是由顺序,选择和循环三种基本结构组成; 结构化程序设计方法的四条原则是,1,自顶向下; 2,逐步求精; 3.
模块化; 4,限 制 使 用 g o t o 语句 。
第 11章 C++的面向对象基础知识当数据和过程相互独立时,总存在着用错误的数据调用正确的程序模块或用正确的数据调用了错误的程序模块的可能性。因此,要使数据与程序始终保持相容,已经成为程序员的一个沉重负担。上述这些问题,结构化程序设计方法本身是解决不了的,
到了 70年代末期,结构化程序设计语言和结构化分析与设计已无法满足用户需求的变化,于是面向对象技术开始浮出水面。
第 11章 C++的面向对象基础知识
11.1.2面向对象的程序设计方法一.面向对象的由来和发展面向对象方法起源于面向对象语言,编程语言得到应用和发展的同时,面向对象的方法得到了发展 。和任何事物一样,面向对象语言也经历了它的发生、发展阶段,走向成熟。
1.在 60年代初期,Algo语言使封装思想诞生 。
2.在 60年代后期,Simula引入对象和消息机制,对象和对象之间可以通过发送消息来进行相互通信,这就是导致了数据封装与通信思想的产生。
第 11章 C++的面向对象基础知识
3.到了 70年代,都许多语言如 CLU,Ads,Modula-2等都开始支持数据与封装,这导致了抽象数据类型发展。
4.1980年,出现 Smalltalk-80商品化的面向对象语言,
它是纯粹的面向对象编程语言。
5.80年代中期到 90年代,出现了大批面向对象语言,
面向对象语言趋于成熟,从此面向对象方法走向实用。
二.面向对象的基本思想其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。
第 11章 C++的面向对象基础知识三.面向对象的基本概念
1.对象:特性 +行为第一个面向对象的程序设计语言是 60年代开发的 Simula—
67。其目的是为了解决模拟问题。典型的模拟问题是银行出纳业务,包括出纳部门、顾客、业务、货币的单位等大量的
“对象”。把那些在程序执行期间除了状态之外其他方面都一样的对象归在一起,构成对象的“类”,这就是“类”一词的来源。类描述了一组有相同特性(数据元素)和相同行为(函数)的对象。
2.继承:类型关系特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。
第 11章 C++的面向对象基础知识一个 类可以是多个一般类的特殊类,它从多个一般类中继承了 属性与服务,这称为多继承。例如,客轮是轮船和客运工 具的特殊类。在 java语言中,通常我们称一般类为父类,特 殊类为子类。
3.封装性封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义:
把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界,只保留有限的对外接口使之与外部发生联系。
4,多态性对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。
第 11章 C++的面向对象基础知识
11.2 C++对 C的扩充
11.2.1 C++语言源程序的编译为了解 C++语言源程序的编译过程首先介绍一些基本术语:
1.源程序:用源语言写的有待翻译的程序,称为“源程序”。 源程序可以是汇编语言,也可以是高级程序设计语言,
所以用它们写出的程序都是源程序。
2.目标程序:是源程序通过翻译加工以后所生成的程序。
目标程序可以用机器语言表示,也可以用汇编语言或其他中间语言表示。
3.翻译程序:是指用来把源程序翻译为目标程序的程序。
对翻译程序来说,源程序是它的输入,而目标程序则是其输出。
第 11章 C++的面向对象基础知识
11.2.2基本数据类型
1,C++类型分类
C++的数据类型有基本数据类型和非基本数据类型。基本数据类型是 C++内部预先定义的数据类型。主要有整型、
字符型、实型、布尔型这四种基本类型。非基本数据类型包括指针、数组、结构、类等。
2.整型标准 C++中 6种整型 short,int,long,unsigned short、
unsigned int,unsigned long。以在十六位计算机中表示为例它们的范围如下表 11.2-1:
第 11章 C++的面向对象基础知识类型 说明 长度(字节) 范围
short 短整型 2 -32768~32767
int 整型 2 -32768~32767l
long 长整型 4- 2147483648~21474
83647
unsigned
short
无符号短整型
2 0~65535
unsigned int 无符号整型 2 0~65535
unsigned
long
无符号长整型
4 0~4294967295
第 11章 C++的面向对象基础知识
3.字符型字符文字由单引号‘限定,字符值以整型的方式存储。
【 例 11.1】 字符变量
int main()
{//打印字符和已在内部存储的整型值
char c=ˊ Aˊ ;
cout <<"c="<<c<<",int(c)="<<int(c)<<endl;
c=ˊ tˊ ;
cout<<"c="<<c<<",int(c)="<<int(c)<<endl;
}
第 11章 C++的面向对象基础知识运行结果:
c=A,int(c)=65
c=t,int(c)=116
由于字符值被用于输入和输出,因此它们表现为字符的形式而不是整型的形式:字符 A是以字母 A的形式而不是以它的内部表示的整数值 65的形式被打印出来。程序中用类型转换运算符 int()将其内部对应的整型值展示出来。这就是字母的 ASCII码。字符型的范围如下表 11.2-2:
类型 说明 长度(字节) 范围
char 字符型 1 -128~127
unsigned char 无符号字符型
1 0~255
第 11章 C++的面向对象基础知识
4.实型
C++支持 3种实数型,float,double,long double。在大多数系统中,double使用 float两倍的字节数。典型的是 float
使用 4字节,double使用 8字节,long double使用 8,10,12
或 16字节。实型的范围如下表 11.2-3:
类型 说明 长度(字节)
float 浮点型 4
double 双精度型 8
Long double 长双精度型 10
第 11章 C++的面向对象基础知识
5.布尔型布尔型变量只能取两个值,false和 true。这两个值被存为 0和 1。
标准 C++中,布尔型被称为 bool。
【 例 11.3】 布尔类型变量
int main()
{//打印布尔变量的值
bool flag=false;
cout<<"flag="<<flag<<endl;
flag=true;
cout<<"flag="<<flag<<endl;
}
第 11章 C++的面向对象基础知识运行结果:
flag=0
flag=1
注意 false值被打印成整数 0而 true值被打印成整数 1。
6.数据类型转换
c++中数据类型转换有两种,即隐式类型转换和显式类型 转换。 隐式类型转换 由编译器自动完成,当编译器遇到不同类型的数据参与同一运算时,会自动将它们转换成相同类型后在进行运算。隐式类型转换按从低到高的顺序进行。 显式类型转换它是程序员显式指出的类型转换,转换形式有两种,〈 类型名 〉
(表达式)( 〈 类型名 〉 ) 表达式通过类型的显式转换可以将“表达式”转换成适当的类型。
第 11章 C++的面向对象基础知识
11.2.3变量的定义变量名要遵守以下规则:
1) 不能是 C++保留字 。
2)第一个字符必须是字母或下划线。
3)中间不能有空格。
变量就是值可变的量,每个变量由一个变量名唯一标识,同时,每个变量又具有一个特定的数据类型。
类型标志着这个变量将来的用法以及它将保存哪种类型的数据值。
1.命名变量名第 11章 C++的面向对象基础知识可以在一个语句里建立多个同一类型的变量,方法是在类型后写上多个变量名,中间用逗开。例如:
unsigned myage,myweight;
long area,width,length;
在同一语句里不能混合定义不同类型的变量
3.变量赋值与初始化用赋值运算符,=”给变量赋值。
例如,int depth; depth=5;
也可在定义时直接给变量赋值。在定义的同时,赋给变量一个初始值,称为变量的初始化。例如,int depth=5; //初始化第 11章 C++的面向对象基础知识在定义时也可以初始化多个变量。例如,int depth=5,
length=6;不是所有的变量在定义时都需要初始化。例如:
double area,radius=15; 该变量定义并不是将 15同时赋给这两个变量,而是变量 radius初始化为 15,area只是定义,没有被初始化。
4.用 typedef定义自己的变量类型在 C++中可以利用 typedef定义自己的变量类型,其形式为,typedef〈 类型说明 〉 ; 〈 类型说明 〉 类似于变量说明,只是变量名用类型名代替了,实际上,这等于定义了一个同义词,
这种方式与创建一个新的类型是不同的。 Typedef没有实际地定义一个新的数据类型,在建立一个 typedef类型时没有分配内存空间。例如:
第 11章 C++的面向对象基础知识
typedef int depth;
typedef char string[8];
使用自定义类型有几点好处:一是可以更好地表达程序员的意思,如用 depth来表示将要定义的标识符是属于深度一类的数据,用 string表示程序员想要定义的是一个字符串,这比直接用系统预定义的类型清晰得多;二是简单方便,一些数据类型可以用简单的类型标识符来表示,不用每次都麻烦地写复杂的定义。
第 11章 C++的面向对象基础知识
1,4,4 C++的函数原型函数原型是一条程序语句,它由函数返回类型 ﹑ 函数名和参数表构成,形式为:返回类型 函数名(参数表);
在 C++中,函数声明就是函数原型。在 C++中,函数的声明可以在主程序以前,也可以在主程序之後。程序:使用函数 C++版本(函数的声明在主程序以前)
如果函数在主程序之后声明,在主程序以前必須有一個叫做 函数原型 的語句。函数原型告訴 C++ 編譯程序参数的数据類型、参数的数目及函数回传的数据類型,這些資料必須和函数的声明一致。
第 11章 C++的面向对象基础知识在数据原型中,参数名称是不需要的,就算有也不一定要和函数声明的一样。例如,函数原型
float power(float base,int n);
可以寫成
float power(float,int);
第 11章 C++的面向对象基础知识
11.2.5 常量说明一,常类型 const
常数型是指使用类型修饰符 const说明的类型,常类型的变量或对象的值是不能被更新的。因此,定义或说明常类型时必须进行初始化.
二.常量分类
1.一般常量
2.常对象
3.常指针第 11章 C++的面向对象基础知识
1.一般常量一般常量是指简单类型的常量。
定义或说明一个常数组可采用如下格式:
<类型说明符 > const <数组名 >[大小 ]
或者 const <类型说明符 > <数组名 >[大小 ]
例如,int const a[5]={1,2,3,4,5};
第 11章 C++的面向对象基础知识
2.常对象常对象是指对象常量,定义格式如下:
<类名 > const <对象名 >
或者 const <类名 > <对象名 >
定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符 const可以放在类名后面,也可以放在类名前面,
第 11章 C++的面向对象基础知识
3.常指针下面定义的一个指向字符串的常量指针:
char * const prt1 =stringprt1;
其中,ptr1是一个常量指针,
下面赋值是非法的,ptr1=stringprt2;
而下面的赋值是合法的,*ptr1="m";
因为指针 ptr1所指向的变量是可以更新的,不可更新的是常量指针 ptr1所指的方向 (别的字符串 ).
第 11章 C++的面向对象基础知识
11.2.6 C++的注释语句一,什么是注释注释是程序员为读者作的说明,是提高程序可读性的一种手段,
一般可将其分为两种:序言注释和注解性注释,前者用于程序开头,说明程序或文件的名称,用途,编写时间,编写人及输入输出说明等,后者用于程序中难懂的地方,
第 11章 C++的面向对象基础知识二,二,注释的书写
1,C++风格的注释为" //"之后的内容,直到换行,注释仅供阅读程序使用,是程序的可选部分,在生成可执行程序之前,C++忽略注释,并把每个注释都视为一个空格,
2,另外,C++还兼容了C语言风格的注释,是指符号" /*"与" */"之间的任何字符串,这些字符可以跨过多行,
第 11章 C++的面向对象基础知识
11.2.7 C++的标准 I/O操作所有用到标准输入输出的C++程序都必须包含
iostream这个预处理伪指令,标识符 iostream是标准
C++库中一个文件的名字,格式 为,include
<iostream.h>,iostream.h是系统定义的一个头文件,
它设置了C++的 I/O相关环境,定义输入输出流对象 cout与 cin等,
一,输出二,输入第 11章 C++的面向对象基础知识一.输出,C++还提供了一些操纵符,可以直接嵌入到输入
/输出语句中来实现I/O格式控制.在使用 setprecision和
setw操纵符时要在程序开头包含 iomanip.h.
操纵符名 含义
dec 数值数据采用十进制表示
hex 数值数据采用十六进制表示
oct 数值数据采用十进制表示
ws 提取空白字符
endl 插入换行符,并刷新流
ends 插入空字符
setprecision(int) 设置浮点数的小数位数 ( 包括小数点 )
setw(int) 设置域宽第 11章 C++的面向对象基础知识
1,输出常数用 cout可以显示数字和字符,可以输出常数,
例,#include <iostream.h>
void main( )
{ int n=50;
float f=20.3;
cout<<"n="<<n<<endl;
cout<<"f="<<f<<endl;}
运行结果为:
n=0
f=20.3000
第 11章 C++的面向对象基础知识三个常用的控制符是 hex,oct和 dec,它们分别对应16进制数,
8进制数和十进制数的显示,这三个控制符在 iostream.h头文件中定义,
#include <iostream.h>
void main( )
{int number=1001;
cout<<"decimal:"<<dec<<number<<endl
<<"hexadecimal:"<<hex<<number<<endl
<<"octal:"<<oct<<number<<endl;}
运行结果为:
decimal:1001
hexadecimal:3e9
octal:1751
2,输 出 八 进 制 和 十 六 进 制 数第 11章 C++的面向对象基础知识
3.设置值的输出宽度除了使用空格来强行控制输出间隔外,还可以用 setw(n)
控制符,如果一个值需要比 setw(n)确定的字符数更多的字符,则该值将使用它所需要的所有字符,
例,Float amount=3.14159;
cout<<setw(4)<<amount<<endl;
其运行结果为:3,14159,它并不按4位宽度,而是按实际宽度输出,如果一个值的字符数比 setw(n)确定的字符数个数更少,则在数字字符前显示空白,不同于其他控制符,setw(n)仅仅影响下一个数值输出,换句话说,使用 setw设置的间隔方式并不保留其效力,
第 11章 C++的面向对象基础知识
4,控制浮点数值显示使用 setprecision(n)可控制输出流显示浮点数的数字个数,C++默认的流输出数值有效位为6,
第 11章 C++的面向对象基础知识二.输入当程序需要执行从键盘输入时,可以使用抽取操作符" >>"从 cin输入流中抽取字符,
例,Int myage;
cin>>myage;
不管把什么基本数据类型的名字或值传给流,它都能懂,Cin可以调整行,自动识别变量位置和类型,它能够知道抽取变量的类型,
第 11章 C++的面向对象基础知识
11.2.8 函数参数的缺省在 C++中函数可以使用缺省参数,例:
void PutHzxy(char *str,int x=-1,int y=-1)
{ if (x==-1) x=wherex();
if (y==-1) y=wherey();
moveto(x,y)
PutHz(str);}
可以有两种方式调用函数 PutHzxy( ),例如:
PutHzxy("C++语言 ");//使用缺省参数,在当前位置输出
PutHzxy("C++语言 ",10,10);//没有使用缺省参数第 11章 C++的面向对象基础知识
11.3 C++程序结构我们从最简单的程序例子来分析 C++的程序组成。
例:下面是一个完整的输出程序 。
#include<iostream.h>
void main( )
{cout<<"hello,world!"<<endl;}
运行结果为,hello,world!
C++的程序结构由注释,编译预处理和程序主体组成,
第 11章 C++的面向对象基础知识一,注释注释是程序员为读者作的说明,是提高程序可读性的一种手段,
二,编译预处理每个以符号,#,开头的行,称为编译预处理行,如,#include”
称为文件包含预处理命令,编译预处理是C ++组织程序的工具,
三,程序主体
main( )表示主函数,每一个 C++程序都必须有一个 main( )函数,Main( )作为程序的入口,Main( )前面的 void表示该 main( )
函数没有返回值,函数体用花括号 { }括起来,描述一个函数所执行算法的过程称为函数定义,例如,这里的 main( )函数头和函数体构成了一个完整的函数定义,
第 11章 C++的面向对象基础知识例如,下面的程序求一个表达式的值,
#include<iostream.h>
void main( )
{int a,b,result;
cout<<"please input two number:\n";
cin>>a>>b;
result=3*a-2*b+1;
cout<<"result is "<<result<<endl;
}
运行结果为:
please input two number:
86 12
result is 235
第 11章 C++的面向对象基础知识
11.4 面向对象的程序设计的重要特征
11.4.1 类类是一种复杂的数据类型,构成了实现 C++面向对象程序设计的基础,它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体 。 因此,在面向对象中类具有更高的抽象性,类中的数据具有隐藏性,类还具有封装性 (Inheritance)。 类是面向对象程序设计的核心,
它实际上是一种新的数据类型,也是抽象类型的工具,
因为类是通过抽象数据类型的方法来实现的一种新的数据类型 。 类是对某一类对象的抽象 。
第 11章 C++的面向对象基础知识类的定义类 (Class)是 C++的精华,是进行封装和数据隐藏的工具。这是面向对象程序设计的一个 重要机制。封装是描述把一个数据结构同操作数据的函数衔接在一起构成一个具有类类型的对象的术语。在 C++中,封装借助于类来达到的。封装要求一个对象应具备明确功能,并有一个接口以便和其它对象相互作用。函数是将逻辑上有关的语句和数据集合在一起,主要用于执行;而类则是逻辑上有关的函数及其数据的集合,它主要不是用于执行,而是提供所需要的资源。在使用一个类之前必须先定义类 。
第 11章 C++的面向对象基础知识定义一个类的语法格式如下所示:
class <类名 >
{
private:
<私有成员数据及函数 ;>
protected:
<保护成员数据及函数 ;>
public:
<公共成员数据及函数 ;>
};
第 11章 C++的面向对象基础知识其中,class是定义类的关键字。 <类名 >是一种标识符,
一对花括号内是说明部分(包括前面的类头)说明该类的成员。类的成员包含数据成员和成员函数两部分。一个类含有私有 (private)成员、保护成员 (protected)和公有成员
(public)三部分。它们在类体内(即一队花括号内)出现的先后顺序无关,并且允许多次出现,用它们来说明类成员的访问权限。默认时在类中定义的项都是私有的。私有变量和函数只能被该类本身的成员函数存取或调用;保护成员除可以被本类中的成员函数访问外,还可以被本类派生的类的成员函数访问,因此用于类的继承;公有成员可以被本类以外的函数访问,是类与外部的接口。
第 11章 C++的面向对象基础知识类是面向对象程序设计最基本的单元,在设计面向对象程序时,首先要以类的方式描述实际待解决的问题,也就是将问题所要处理的数据定义成类的私有或公共类型的数据,同时将处理问题的方法定义成类的私有或公有的成员函数。其中,<各个成员函数的实现 >是类定义中的实现部分,这部分包含所有在类体内说明的函数的定义。如果一个成员函数在类体内定义了,实现部分将不出现。如果所有的成员函数都在类体内定义,则实现部分可以省略。
第 11章 C++的面向对象基础知识例如,下面给出一个关于日期的类的定义,该类的对象将是某一个具体的日期。
class TDate
{
private:
int year,month,day;
public:
int IsLeapYear();
void Print();
};
第 11章 C++的面向对象基础知识定义类时的注意事项
在类体中不允许对所定义的数据成员进行初始化 。
类中的数据成员类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是对象。
当一个类的对象作为这个类的成员时,如果另一个类的定义在后,需要提前说明。
一般,在类体先说明公有成员,它们是用户不感兴趣的。在说明数据成员时,一般按数据成员的类型大小,
由小到大说明,这样可提高时空利用率。
经常习惯地将类定义的说明部分或者整个定义部分
(包含实现部分)放到一个头文件中。
第 11章 C++的面向对象基础知识
11.4.2 对象在 C++中,对象是声明为类类型的一个数据项,
是类的实际变量 。 程序员也可以定义类的变量 。 这个定义的类的变量在 C++中就被称为对象 。 对象有时也称为类的实例 (Instance)。 由此可见,类是程序中的一个静态的概念,而对象是程序中的一个动态的概念 。
对象是类的实例 。 对象是属于某个已知的类 。 在创建对象中,类被用作模板,类和对象的关系就如同整型
int与整型变量之间的关系 。 因此,定义对象之前,一定要先定义好该对象的类 。
第 11章 C++的面向对象基础知识对象的定义在 C++中有两种方法可以定义类的对象:第一种是在定义好类后,再定义类的对象,也是最常用的一种对象的定义方法,其一般格式如下:
类名 对象 1[,对象 2,...];
例如,TDate date1,data2;
其中,Tdate 为日期类的类名,date1和 date2是一般的对象名。除此之外,还可以是指向对象的指针或引用名,也可以是对象数组名。当有多个对象名时,
多个对象名之间有逗号分隔。
例如,Tdate*Pdate,data[31];
第 11章 C++的面向对象基础知识还有一种是在定义类的同时直接定义类的对象,即在定义类的右大括号,}”后直接写出属于该类的对象名表列,即:
class 类名
{
成员变量表列 ;
成员函数表列 ;
}对象名表列 ;
第 11章 C++的面向对象基础知识对象成员的表示方法一个对象的成员就是该对象的类所定义的成员。对象成员有数据成员和成员函数。
一般对象的成员表示如下:
<对象名 >.<成员名 >
或者
<对象名 >.<成员名 >(<参数表 >)
前者用来表示数据成员的,后者用来表示成员函数的。
第 11章 C++的面向对象基础知识例如,date1的成员表示为:
date1.year,date1.month,date1.day
分别表示 Tdate类的 date1对象的 year成员,month成员 和 day成员。
Date1.SetDate(int y,int m,int d)
表示 Tdate类的 date1对象的成员函数 SetDate()。
这里,.是一个运算符,该运算符的功能是表示对象的成员,用法同上。
第 11章 C++的面向对象基础知识指向对象的指针的成员表示如下:
<对象指针名 >-><成员名 >
或者
<对象指针名 >-><成员名 >(<参数表 >)
这里的 ->是一个表示成员的运算符,它用来表示指向对象的指针的成员。下面的两种表示是等价的:
<对象指针名 >-><成员名 > 与 (*<对象指针名 >).<成员名 >
这对于成员函数也适用。
第 11章 C++的面向对象基础知识由同一个类所创建的对象的数据结构是相同的,类中的成员函数是共享的。两个不同的对象的名字是不同的,它们的数据结构的内容(即数据成员的值)是不同的。因此,系统对已经定义的对象仅仅给它分配数据成员变量,而一般数据成员又都为私有成员,不同对象的数据成员的值可以是不同的。
第 11章 C++的面向对象基础知识例如:分析下列程序的输出结果。
#include<iostream.h>
#include"tdate.h"
void main()
{
Tdate date1,date2;
date1.SetDate(1996,9,1);
date2.SetDate(1998,10,10);
cout<<leap<<endl;
date1.Print();
date2.Print();
}
第 11章 C++的面向对象基础知识执行该程序后,输出结果如下:
1
1996.9.1
1998.10.10
该程序的主函数中,定义了两个对象 date1和 date2,并通过成员函数 SetDate()个对象 date1和 date2赋值。程序中,通过成员函数 IsLeapYear()判断对象 date1的年份
(1996)是否是闰年,本例输出为 1表示 1996年是闰年。
最后,通过调用成员函数 Print()输出显示对象 date1和
date2的数据成员的值,即年、月和日。
第 11章 C++的面向对象基础知识
11.4.3 构造函数和析构函数对象的意义表达了现实世界的实体,因此,一旦建立对象,必须有一个有意义的初始值。 C++规定与类同名的成员函数是构造函数。建立和初始化对象的过程专门由该类的构造函数来完成。构造函数的功能是在创建对象时,使用给定的值来将对象初始化。这个构造函数很特殊,只要对象建立,它马上被调用,给对象分配空间和初始化。
第 11章 C++的面向对象基础知识
C++另有一种析构函数,它也是类的成员函数,它的功能是用来释放一个对象的。在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。
例如,一张桌子要扔掉,必须将桌子里面的东西拿来这些东西可能有用,不能随捉系一起扔。类似这些事就由析构函数来完成。
第 11章 C++的面向对象基础知识构造函数的特点如下:
构造函数是成员函数,函数体可写在类体内,也可以写在类体外。
构造函数是一个特殊的函数,该函数的名字与类相同,该函数不指定类型说明,它有隐含的返回值,
该值由系统内部使用。该函数可以有一个参数,也可以有多个参数。
构造函数可以重载,即可以定义多个参数个数不同的函数。
程序中不能直接调用构造函数,在创建对象时系统自动调用构造函数。
第 11章 C++的面向对象基础知识析构函数的特点如下:
析构函数是成员函数,函数体可以写在类体内,也可以写在类体外。
析构函数也是一个特殊的函数,它的名字同类名,并在前面加,~”字符,用来与构造函数加以区别。析构函数不指定数据类型,并且没没有参数。
一个类中只可能定义一个析构函数。
析构函数可以被调用,也可以调用。两种情况下,析构函数被自动调用。若一个对象被定义在一个函数体内,则当这个函数结束时,该对象的析构函数被自动调用;当一个对象用 new运算符被动态创建,在用
delete运算符释放它时,delete会自动调用析构函数。
第 11章 C++的面向对象基础知识在类定义时没有定义任何构造函数时,则编译器自动生成一个不带参数的缺省构造函数,其格式如下:
<类名 >::<缺省构造函数名 >()
{
}
按构造函数的规定,缺省构造函数名同类名。缺省构造函数的怎样格式也可以由程序定义在类体中。
在程序中定义一个对象而没有指明初始化时,则编译器便按缺省构造函数来初始化该对象。
第 11章 C++的面向对象基础知识用缺省构造函数对对象初始化时,则将对象的所有数据成员都初始化为零或空。
同理,如果一个类中没有定义析构函数时,则编译系统也生成一个称为缺省析构函数,其格式如下:
<类名 >::~<缺省析构函数名 >
{
}
<缺省析构函数名 >即为该类的类名。缺省析构函数是一个空函数。
第 11章 C++的面向对象基础知识
11.4.4 继承性继承是面向对象程序设计中最重要的机制 。 这种机制改变了过去传统的非面向对象程序设计中那种对不适合要求的用户定义数据类型进行改写甚至重写的法克服了传统程序设计方法对编写出来的程序无法重复利用程序资源的浪费的缺点 。 面向对象程序设计的继承机制给我们提供了无限重复利用程序资源的一种途径 。
第 11章 C++的面向对象基础知识通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称父类。由已存在的类派生出的新类称为派生类,又称为子类。
第 11章 C++的面向对象基础知识在 C++语言中,一个派生类可以从一个基类派生,
也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生 第一张幻灯片 的继承称为多继承。
单继承形成了类的层次,如图 (a)和 (b)所示。
A
B C
X Y
Z
(a) 单继承 (b) 多继承第 11章 C++的面向对象基础知识派生类的定义格式:
单继承的定义格式如下:
class<派生类名 >:<继承方式 ><基类名 >
{
<派生类新定义成员 >
};
其中,<派生类名 >是新定义的一个类的名字,它是从
<基类名 >中派生的,并且按指定的 <继承方式 >派生的。
第 11章 C++的面向对象基础知识
<继承方式 >常使用如下三种关键字给予表示:
public 表示公有基类;
private 表示私有基类;
protected 表示保护基类。
多继承的定义格式如下:
class <派生类名 >:<继承方式 1><基类名 1>,<继承方式
2><基类名 2>,…
{
<派生类新定义的成员 >
};
第 11章 C++的面向对象基础知识派生类的三种继承方式公有继承 (public)、私有继承
(private)和保护继承 (protected)是常用的三种继承方式。
1,公有继承 (public)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。
2,私有继承 (private)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
第 11章 C++的面向对象基础知识
3,保护继承 (protected)
保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元所访问,基类的私有成员仍然是私有的。将上述三种不同继承方式的基类特性与派生类特性见表 11.5。
第 11章 C++的面向对象基础知识继承方式 基类特性 派生类特性公有继承 public
protected
private
public
protected
不可访问私有继承 public
protected
private
private
private
不可访问保护继承 public
protected
private
protected
protected
不可访问第 11章 C++的面向对象基础知识对于公有继承方式:
(1) 基类成员对其对象的可见性:公有成员可见,其他不可见。这里保护成员同于私有成员。
(2) 基类成员对派生类的可见性:公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
(3) 基类成员对派生类对象的可见性:公有成员可见,其他成员不可见。
第 11章 C++的面向对象基础知识对于私有继承方式:
(1) 基类成员对其对象的可见性:公有成员可见,其他成员是不可见。
(2) 基类成员对派生类的可见性:公有成员和保护成员是可见的,而私有成员是不可见的。
(3) 基类成员对派生类对象的可见性:所有成员都是不可见的。
对于保护继承方式:
该继承方式与私有继承方式的情况相同。两者区别仅在于对派生类成员而言,对基类成员有不同的可见性。
第 11章 C++的面向对象基础知识
11.4.5 作用域运算符类的方法的具体实现和普通函数的具体实现只是在函数的头部有略微不同的格式。一般来说,如果类的方定义是在类的外部实现的,则在定义方法时必须把类名放在方法名之前,中间用作用域运算符(,::”)隔开,
其一般形式如下所示:
类名,:方法名第 11章 C++的面向对象基础知识这样,即使几个类中的方法名相同,也可以用这种形式把它们区分开来。和普通函数一样,类的方法也应该既有返回值类型,也有参数表列(当然也可以没有参数)。一个方法的头部各部分如下所示:
访问控制,函数返回值 函数名(参数表列) ;
第 11章 C++的面向对象基础知识运算符,:用来连接类名和成员名,以告知编译程序这个成员属于哪个类。但作用域运算符还有其它的用途:它允许在一个封闭的作用域里村区与局部说明相同的名字。例如:
int i; //全局变量
void f()
{
int i; //局部变量
i=10; //使用局部变量
}
第 11章 C++的面向对象基础知识但是,如果函数 f()要存取全局变量 i,只需要将运算符,:
置于 i之前即可。如下所示:
int i; //全局变量
void f()
{
int i; //局部变量
::i=10; //全局变量
}
第 11章 C++的面向对象基础知识
11.4.6 动态内存分配在 C语言里,动态内存分配是通过使用函数 malloc()和
free()实现的。为保持兼容性,C语言的动态内存分配函数仍然为 C++所有。但 C++提供了它自己的、可供选择的基于两个新的运算符 new和 delete的动态分配系统。 C++的动态分配方法有客观的优越性。
运算符 new返回分配的内存的指针,和 malloc()一样,
new从堆里分配内存。如果没有足够的内存满足分配要求,它就返回一个空( Null)指针。 Delete运算符释放
new分配的内存。
第 11章 C++的面向对象基础知识运算符 delete必须用于先前 new分配的有效指针,如果使用了未定义的其他任何类型的指针,就会带来严重问题,如:系统崩溃。
与 malloc()和 free()相比较,new自动分配足够的空间以容纳指定类型的对象,而且不用使用 sizeof运算符,由于容量是自动计算的,所以消除了这方面发生错误的可能性; new自动返回指定类型的指针,不需要显示强制 new
和 delete都可以重载,允许创建定制的分配系统。
第 11章 C++的面向对象基础知识
11.4.7 多态性
C++中允许子类的成员函数重载基类的成员函数。例如,基类和派生类中都定义了计算学费的成员函数:
class Student
{
public:
//….
float calcTuition()
{ //…}
};
第 11章 C++的面向对象基础知识
class GraduateStudent:public Student
{
public:
//…
float calcTuition()
{
//…
}
};
第 11章 C++的面向对象基础知识
void main()
{
Student s;
GtaduateStudent gs;
s.calcTuition(); //调用 Student::calcTuition()
gs.calcTuition(); //调用 GraduateStudent::calcTuition()
}
第 11章 C++的面向对象基础知识在派生类中重载了 calcTuition()成员函数,学生的学费计算与研究生的学费计算方法不同。学生对象 s调用其学费计算函数显然指的是 Student::calcTuition()成员,而研究生对象 gs调用其学费计算函数时,两个重载函数都在它自己可使用范围内,C++编译规定,gs.calcTuition()指的是
GraduateStudent::calcTuition()。若派生类没有定义其
calcTuition(),则 gs.calcTuition()才指的是基类
Student::calcTuition()。
第 11章 C++的面向对象基础知识
11.5 小结本章我们介绍了 C++的一些背景知识和特点,包括 C++
的一些词法符号,然后介绍了 C++的数据类型、变量说明和运算符,以及程序的结构。 C++是一种表达式语言,所有的操作都用表达式表示 。一个类具有数据成员,还员函数,通过成员函数可以对数据成员进行操作,并实它的功能。定义一个类后,可以把该类名作为一种数据类型,定义其“变量”(对象)。程序利用点操作符(,)
访问类的公共成员。
第 11章 C++的面向对象基础知识程序可以在类的外部或内部定义它的成员函数,在类的外部定义成员函数时,必须指出所属的类名,并用符
(,:)把类名和函数名连接起来。
类的成员,包括数据和函数,都可以被说明为公有、
保护或私有。公有成员可以在程序中任意被访问,而保护或私有成员只能被这个类的成员函数所访问。类是一种复杂的数据类型,它是抽象数据类型的实现,是数据和相关操作的封装体。
第 11章 C++的面向对象基础知识构造函数是一种用于创建对象的特殊成员函数,人们调用一个构造函数来为类对象分配空间,给它的数据成员赋初值,以及其它请求资源的工作。每个类对象都必须在构造函数中诞生,一个类可能拥有一个或多个构造函数,编译程序为了决定调用哪个构造函数,要把对象声明中使用的变元(实参)和构造函数的参数进行较该过程与普通重载函数和匹配函数调用的方法相同。