`

基于对象的设计(5)

阅读更多
<script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>

重载函数在运行时刻的行为与非重载函数完全一样,主要的负担是在编译时刻用来决定

该调用哪个实例所需要的时间,如果C++不提供函数重载支持,那么我们就必须为程序中

每个函数都要提供一个独一无二的名字,第9 章将详细讨论函数重载的内容

我们为IntArray 类指定了下面三个构造函数

class IntArray {

public:

explicit IntArray( int sz = DefaultArraySize );

IntArray( int *array, int array_size );

IntArray( const IntArray &rhs );

// ...

private:

static const int DefaultArraySize = 12;

// ...

};

构造函数

IntArray( int sz = DefaultArraySize );

被称为缺省构造函数default constructor ,因为它不需要用户提供任何参数,我们

现在不打算解释这个,缺省构造函数声明中出现的关键字explicit 之所以显示,它仅仅是为了完

整性,如果程序员提供参数则该值将被传递给构造函数,例如

IntArray array1( 1024 );

将参数1024 传递给构造函数,另一方面,如果用户不指定长度,那么构造函数将使用

DefaultArraySize 的值,例如

IntArray array2;

将导致用DefaultArraySize 的值来调用,构造函数被声明为static 的数据成员是一类特

殊的共享数据成员,无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份,

这是在类的所有对象之间共享数据的一种方式,13.5 节有全面的讨论。

下面是缺省构造函数的一个简化实现版本,简化到没有考虑出错的可能性,可能出现

什么错误呢?本例中有两个首先提供给程序的动态内存不是无限的,因此new 表达式

有可能失败,2.6 节中将介绍如何处理这种情况。第二,传递给参数sz 的值可能是无效的。

例如负数或0,或者一个很大的值,以至于无法存储在int 类型的变量中

IntArray::

IntArray( int sz )

{

// 设置数据成员

size = sz;

ia = new int[ _size ];

// 初始化内存

for ( int ix=0; ix < _size;

++ix )

ia[ ix ] = 0;

}

这是我们第一次在类体的外面定义类的成员函数,惟一的语法区别是要指出成员函数属

于哪个类,这可以通过类域操作符class scope operator 来实现

IntArray::

双冒号:: 操作符被称为域操作符scope operator,当与一个类名相连的时候,像上

面例子中那样它就成为一个类域操作符,我们可以非正式地把域看作是一个可视窗口,全

局域的对象在它被定义的整个文件里一直到文件末尾都是可见的,在一个函数内被定义

的对象是局域的local scope,它只在定义其他的函数体内可见,每个类维持一个域,在这

个域之外,它的成员是不可见的。类域操作符告诉编译器后面的标识符可在该类的范围内被找到,本例中

IntArray::

IntArray( int sz )

告诉编译器IntArray()函数被定义为IntArray 类的成员,尽管程序域不是我们现在应该关注的事情,但是最终我们还是要理解域的概念,在第8 章中我们将详细讲解程序域,而类域将在13.9 节中特别讨论。

IntArray 类的第二个构造函数用内置的整数数组初始化一个新的IntArray 类对象,它需

要两个参数,一个是实际的数组,另一个参数指明数组的大小,例如

int ia[10] = {0,1,2,3,4,5,6,7,8,9};

IntArray iA3(ia,10);

这个构造函数的实现几乎与第一个构造函数相同,这里我们又一次没有保护自己的代码

IntArray::

IntArray( int *array, int sz )

{

// 设置数据成员

size = sz;

ia = new int[ _size ];

// 拷贝数据成员

for ( int ix=0; ix < _size; ++ix )

iz[ix ] = array[ ix ];

}

最后一个IntArray 构造函数用另外一个IntArray 对象来初始化,当前的IntArray 对象对

于下面两种形式无论是哪一种它都将被自动调用

IntArray array;

// 等价的初始化方式

IntArray ia1 = array;

IntArray ia2( array );

这种构造函数被称为类的拷贝构造函数copy constructor,在后面的章节中我们将会

看到更多的示例,下面的实现再次忽略了可能出现的运行时刻程序异常

IntArray::

IntArray( const IntArray &rhs ){

// 拷贝构造函数

_size = rhs._size;

ia = new int[ _size ];

for (int ix = 0; ix < _size; ix++ )

iz[ ix ] = rhs.ia[ ix ];

}

本例引入了一种新的复合类型引用reference, 即IntArray &rhs,引用是一种没有

指针语法的指针,因此我们写成rhs._size 而不是rhs->_size 与指针一样,引用提供

对对象的间接访问,3.6 节中我们将对指针和引用作更多的介绍

注意这三个构造函数都是以相似的方式来实现的,一般来说,当两个或多个函数重复

相同的代码时,就会将这部分代码抽取出来形成独立的函数,以便共享以后如果需要

改变这些实现,则只需改变一次,而且这种实现的共享本质更容易为大家所理解。

怎么样把构造函数中的代码抽取出来形成独立的共享函数呢?下面是一种可能的实现

class IntArray {

public:

// ...

private:

void init( int sz, int *array );

// ...

};

void

IntArray::

init( intsz, int *array )

{

_size = sz;

ia = new int[ _size ];

for ( int ix=0; ix < _size; ++ix )

if ( ! array )

ia[ ix ] = 0;

else ia[ ix ] = array[ ix ];

}

三个构造函数可重写为

IntArray::IntArray( int sz ){ init( sz, 0 ); }

IntArray::IntArray( int *array, int sz )

{ init( sz, array ); }

IntArray::IntArray( const IntArray &rhs )

{ init( rhs.size, rhs.ia ); }

类机制还支持特殊的析构成员函数destructor member function,每个类对象在被程序

最后一次使用之后,它的析构函数就会被自动调用,我们通过在类的名字前面加一个波浪线

~ 来标识析构函数。一般地,析构函数会释放在类对象使用和构造过程中所获得的资源,

例如,在IntArray 的析构函数中,它会删除构造时分配的内存,我们将在第14 章详细讨论

构造函数和析构函数,下面是我们的实现

class IntArray {

public:

// 构造函数

explicit IntArray( int size = DefaultArraySize );

IntArray( int *array, int array_size );

IntArray( const IntArray &rhs );

// 析构函数

~IntArray() { delete [] ia; }

// ...

private:// ...

};

除非用户能够很容易地通过索引访问单个元素,否则数组类就没有更实际的用处,例如

我们的类需要支持下面的一般用法

IntArray array;

int last_pos = array.size()-1;

int temp = array[ 0 ];

array[ 0 ] = array[ last_pos ];

array[ last_pos ] = temp;

我们通过提供专用于一个类的下标操作符实例来支持索引IntArray 类对象,下面

是支持这种用法的一个实现

#include <cassert>

int&

IntArray::

operator[]( int index )

{

assert( index >= 0 && index < size );

return ia[ index ];

}

一般而言,C++语言支持操作符重载operator overloading,这样,就可以为特定的类类

型定义新的操作符实例,典型地类提供一个或多个赋值操作符、等于操作符可能还有

一个或多个关系操作符以及iostream 输入和输出操作符,3.15 节有关于操作符重载的更

进一步的说明,在第15 章我们将详细讨论操作符重载。

类定义以及相关的常数值或typedef 名通常都存储在头文件中,并且头文件以类名来命

名。因此,假如我们创建一对头文件IntArray.h 和Matrix.h,则所有打算使用IntArray 类或Matrix 类的程序就都必须包含相关的头文件。

类似地,不在类定义内部定义的类成员函数都存储在与类名同名的程序文本文件中,例如我们将创建一对程序文本文件IntArray.C 和Matrix.C ,用来存储相关类的成员函数。

记住程序文本文件的后缀因编译系统而不同,你应该检查自己的系统所使用的命名习惯。

这些函数不用随每个使用相关类的程序而重新编译,这些成员函数经过预编译之后被保存在

类库中,iostream 库就是这样一个例子。

分享到:
评论

相关推荐

    基于面对对象设计的聊天室源码

    【标题】基于面向对象设计的聊天室源码 在编程领域,面向对象设计(Object-Oriented Design,OOD)是一种广泛采用的软件设计方法,它将复杂的问题空间转化为一组相互协作的对象。本聊天室系统正是以此为核心思想...

    面向对象设计之3_基于UML的图书管理系统的分析与设计说明.pdf

    面向对象设计之3_基于UML的图书管理系统的分析与设计说明 本资源摘要信息主要介绍面向对象设计和UML(Unified Modeling Language)在图书管理系统中的应用。面向对象设计是一种程序设计方法,强调使用对象、类、...

    面向对象课程设计基于avaFX的媒体播放器.zip

    面向对象课程设计基于avaFX的媒体播放器.zip面向对象课程设计基于avaFX的媒体播放器.zip面向对象课程设计基于avaFX的媒体播放器.zip面向对象课程设计基于avaFX的媒体播放器.zip面向对象课程设计基于avaFX的媒体...

    java 门禁系统的面向对象设计

    在IT行业中,面向对象设计(Object-Oriented Design,简称OOD)是一种常用的设计方法论,尤其在Java这样的面向对象编程语言中尤为重要。本篇将详细探讨如何使用Java进行门禁系统的面向对象设计。 门禁系统是用于...

    校园二手交易平台-基于UML面向对象分析与设计.docx

    以下是基于UML的面向对象分析与设计的详细解释: 1. **用例图**: 用例图展示了系统中不同用户(如普通用户和管理员)的角色及其可执行的操作。例如,用户可以注册、登录、发布商品、浏览和购买商品,管理员则可以...

    c#基于面向对象的程序设计

    一个c#基于面向对象的程序设计,已在实践中应用。

    面向对象程序设计课程设计——学生成绩管理系统

    了解当前常用的软件开发工具(Visual C++),要求熟练掌握基于类的程序设计,培养解决实际问题的能力。 设计功能:使用面向对象的程序设计方法,程序的功能主要包括:对学生成绩信息的增、删、查、改等基本功能,并...

    基于面向对象的图书管理系统的设计说明书.pdf

    "基于面向对象的图书管理系统的设计说明书.pdf" 该设计说明书详细介绍了基于面向对象的图书管理系统的设计,包括程序系统需求的详细分解与用例建模,以及类与接口的生成等。该系统的目标是为图书管理员和读者提供...

    对象设计角色、责任和协作.简体中文扫描版

    对象设计常用工具:CRC卡(类别责任协作图 经典教程 POSA中大量使用CRC 在此推荐 作者Rebecca wirfs Brock和Alan McKean在书中讨论了基于责任驱动这一概念框架之下的用户需求 系统架构和设计模式如何共同作用 从而...

    面向对象设计UML实践课后答案

    面向对象设计(Object-Oriented Design,OOD)是一种软件开发方法,它基于“对象”的概念,将现实世界的问题域转化为计算机程序。UML(Unified Modeling Language)是面向对象设计的一种标准化建模语言,用于可视化...

    基于职责设计对象

    基于职责设计对象 决定方法归属于哪个对象和对象之间如何交互,其意义重大,应谨慎从事。 掌握OOD可以通过在实例中学习和在设计中对模式的命名

    基于python的动漫推荐系统的设计与实现代码

    基于python的动漫推荐系统的设计与实现代码 基于python的动漫推荐系统的设计与实现代码 基于python的动漫推荐系统的设计与实现代码 基于python的动漫推荐系统的设计与实现代码 基于python的动漫推荐系统的设计与实现...

    面向对象分析与设计.pdf

    面向对象设计是在分析的基础上进行的,它关注于如何将需求转化为软件系统的内部结构。设计阶段的输出通常包括更详细的类图、活动图、序列图、状态图和组件图等UML模型。设计过程还会确定系统组件的接口和协作方式。 ...

    基于对象识别的机械手高速分拣系统设计研究

    介绍了机械手高速分拣系统的组成(发送端、接收端),并基于嵌入式控制系统对机械手运动进行建模,主要包含运动学模型和逆运动学模型。以工程实现过程中以视觉系统作为机械手引导源,以DELTA机械手作为实现对象,在PC端...

    5. 圆类设计(基于对象的程序设计)(1).cpp

    5. 圆类设计(基于对象的程序设计)(1).cpp

    基于c++的课程设计

    在本次基于C++的课程设计中,主要涉及到的是面向对象编程的概念,包括类的定义、对象的创建、构造函数的使用、成员函数的实现以及类的继承。以下是对这些知识点的详细解释: 1. **类的定义**:类是C++中面向对象...

    基于公理设计方法的工程布局CAD系统设计.pdf

    3. 面向对象的软件设计:面向对象(OOP)是一种编程范式,基于对象的概念,它将数据(对象的属性)和功能(对象的方法)封装在一起,以模拟现实世界中的实体。面向对象设计方法使得软件模块化、易于维护和扩展。 4....

    面向对象程序设计基于QT的陨石撞飞机游戏的设计与实现源码+文档说明(C++期末大作业)

    面向对象程序设计基于QT的陨石撞飞机游戏的设计与实现源码+文档说明(C++期末大作业)面向对象程序设计基于QT的陨石撞飞机游戏的设计与实现源码+文档说明(C++期末大作业)面向对象程序设计基于QT的陨石撞飞机游戏的...

Global site tag (gtag.js) - Google Analytics