按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
所使用的对象的层次结构,然后,直接将此结构映射到面向对象的程
序空间,而不需要做任何修改或仅需要作少量修改就可以使用面向对
象的程序设计方法来实现该结构。这时,编写程序的过程更类似于
“搭积木”,我们可以从很多途径来获得到程序所需使用的各种对
象,然后,将这些对象以一定的层次结构组合起来,从而实现程序的
逻辑结构。
2。1。4 多态和虚函数
在讲述多态之前我们先来看一个问题。仍以前面的图2。2为例,假定
我们已经定义了一个指向哺乳动物类的实例对象的指针,如下所示:
CMammal *pMammal
然后我们定义了一个人类的实例对象和一个狒狒类的实例对象,如下
所示:
CHuman Human;
CBaboon Baboon;
然后,我们可以将指针pMammal指向Human对象,在C++语言中是可以
这样做的:
pMammal=&Human;
也可以将指针指向Human对象:
pMammal=&Baboon;
考查上面的两种情况,我们假定在哺乳动物类、人类和狒狒类中都定
…………………………………………………………Page 44……………………………………………………………
义了一个Eat (吃)方法,很显然,当我们使用下面的代码来调用人类
对象和狒狒类对象的Eat方法时不会遇到什么问题:
Human。Eat();
Baboon。Eat();
但是,现在来考虑下面的代码:
pMammal…》Eat();
当pMammal指向不同的对象时,上面的代码将发生什么样的结果。很
显然,当pMammal指向一个哺乳动物类的实例对象时,上面的代码将
调用哺乳动物类的Eat方法。但是,当pMammal指向一个人类的实例对
象时,上面的代码是调用人类的Eat方法呢,还是仍然调用哺乳动物
类的Eat方法?我们期望的是前面一种情况,这就是类和对象的多态
性。我们期望,当pMammal指向不同的实例对象时,编译器将根据实
例对象的类型调用正确的Eat方法。在C++中,类的多态性是通过虚函
数来实现的。就上面的例子来说,我们将Eat方法定义为一个公有的
虚函数,这样,当pMammal指针指向一个人类的实例对象时,编译器
调用的就是人类的Eat方法,当pMammal指针指向一个狒狒类的实例对
象时,编译器调用的就是狒狒类的实例对象,从而实现了运行时的多
态。
在C++中,多态定义为不同函数的同一接口。从这个定义出发,函数
和操作符的重载也属于多态。
考虑下面定义的两个函数:
int print(char*);
int print(int);
上面的两个不同函数使用同样的函数名,在C++中,这称为函数的重
载。这时,若将一个字符指针传递给print函数,如下所示:
char *sz=〃Hello World!〃;
print(sz);
这时,编译器调用的是int print(char*),如果将一个整型变量传递
给print函数,如下所示:
int i=0;
…………………………………………………………Page 45……………………………………………………………
print(i);
则编译器调用的是int print(int)。这种根据所传递的参数的不同而
调用不同函数的情形也称作多态。
下面我们来看运算符重载的例子,在下面的过程中,我们为矩阵类重
载了运算符 “+”:
CMatrix operator +(CMatrix; CMatix);
然后使用下面的代码:
int a=1; b=1; c;
CMatrix A(3; 3; 0); B(3; 3; 1); C(3; 3);
c=a+b;
C=A+B;
在上面的例子中,我们定义了三个整型变量和三个类CMatrix的实例
变量,A、B和C均为3' 3的矩阵,其中A中全部元素均置为0,B的全部
元素均置为1。然后将 “+”运算符作用来整型变量和类CMatirx的实
例变量。这时,编译器将表达式c=a+b翻译为
c=operator +(a; b);
而将表达式C=A+B翻译为
C=operator +(A; B)
然后,根据传递参数的不同,调用不同的operator +函数。
与类和对象的多态不同,对于函数和运算符的多态,是在编译过程中
完成的,因此我们将它们称为编译时多态,与此相对,将类和对象的
多态称为运行时多态。
封装性、继承性和多态性是面向对象编程的三大特征,则开始的时
候,你也许对它们还没有非常清晰的概念,但这没有什么关系,当你
使用了一段时间的C++语言,然后再回过头来看这些概念时,你就会
发现对它们有了更深入的认识和了解。事实上,许多的C++程序正是
在使用C++语言进行编程已有相当一段时间时才对这三个概念有了正
确而清晰的认识的。
l 注意:
…………………………………………………………Page 46……………………………………………………………
l 在前面的过程中,我们多次混用了对象和类这两个术语,事实
上,它们之间是有差别的。在C++中,类是一种数据类型,它是一
组相同类型的对象的抽象。在类中定义了这一类对象的统一的接
口。而对象在C++中是指某一数据类型的一个实例,如下面的代码
所示:
l Class CBaloon;
l CBaloon Baloon1;
l CBaloon Baloon2;
l CBaloon Baloon3;
在上面的代码 中,我们声明了一个类CBaloon,这是所有狒狒
对象的抽象,然后,我们使用类来创建了三个不同的实例对
象Baloon1、Baloon2和Baloon3。
然而,尽管类和对象是两个意义不同的概念,但是,它们在
C++语言中是紧密相关的,这使得很多的文档 (包括Visual
C++的联机文档)在有些时候也不加 区分的混用这两个术语。
读者根据相应的上下文,应该能够很方便的辨明它们具体所
指的内容究竟是类还是类的实例对象。
在随后的小节中,我们将讲述如何在C++中实现上面所说的面向对象
的编程概念。
第二节 类的声明和定义
本节讲述在声明和定义类及类中的成员变量和成员函数所需注意的问
题。在本章中,我们使用了传统的C/C++编程风格,即每一个程序都
以一个名为main的主函数为入口,过去常见的MS…DOS应用程序即是这
样的。众所周知,Visual C++ 5。0不支持16位MS…DOS编程,但这并不
意味着我们必须放弃这种编程模式。事实上,我们仍然可以在Visual
C++ 5。0中编译和调试在本章中出现的所有程序,方法是使用Win32
Console Application (Win32控制台应用程序)来编译它们,Win32控
制台API提供了字符方式的应用程序的编程接口,并且,我们仍可以
使用过去所熟知的以main函数为入口的编程方式。除此之外,Win32
平台为控制台应用程序提供了虚拟的一个标准输入和输出设备 (由于
Windows程序共享屏幕和其它所有设备,因此不存在在DOS中的那种标
准输入和输出设备),这样,我们可以使用标准的C语言输入输出函数
scanf和printf,还可以使用标准的C++语言输入和输出流cin和
…………………………………………………………Page 47……………………………………………………………
cout。关于控制台应用程序的内容,可以参考本书的相关章节。
2。2。1 类及其成员变量和成员函数的声明和定义
在C++中,存在三种类类型:类、结构和联合,它们分别使用三个关
键字来声明和定义类:class、struct和union。表2。1给出了不同类
类型之间的差别。
表2。1 三种不同类型的类:类、结构和联合
类 结构 联合
声明和定义时使用 class struct union
的关键字