这是第6章开始介绍C++面向对象编程之前的最后一次面向对象设计任务:完成这个任务并学习第6章之后,就可以开始编写电梯模拟程序。要完成第2章定义的电梯模拟程序,就需要第6章、第7章和第8章介绍的C++方法。然后用第9章和第10章介绍的继承和多态方法馅改电梯模拟程序。
本节介绍对象间的交互帮助读者把对象联系起来。也许读者在第2章、第3章和第4章开发实验室任务时增加了对象、属性和行为。
我们介绍过,大多数C++对象不是自动工作的,而是响应消息刺激,实际上是对象对成员函数的函数调用。
下面要考虑电梯模拟程序中几个类的交互。问题“人按楼层中的按钮”,这里主语是人、宾语是按钮,这就是类之间交互的例子。person类的对象向button类的对象发一个消息,我们把这个消息称为pushButton。上一章把该消息变成了button类的成员函数。
这时.在电梯模拟程序每个类的其他事实中,余下的大概都是类之间的交互,其中有些明显表示类对象之间的交互。但请考虑下列表述:
”persOn waits for elevator door to open"(人等待电梯开门)
上一章列出了电梯门的两个行为,称为opeaDoor和closeDoor,现在要确定哪个类对象发出这些消息。可以确定是电梯本身发出这些消息给电梯门。这些类对象之间的交互隐含在问题陈述中。
现在要继续细化电梯模拟程序中每个类的“其他事实”部分.这时应当主要包含类之间的交互。注意下列几点:
1.谁发送类对象。
2. 发送什么消息。
3. 谁接收类对象。
在每个类中,增加“发往其他类对象的消息”(这种消息也称为“协作”)并列出类之间的其他交互,例如.在person类中,包含项目:
person sends pushButtOn message to the button On that floor
在button类的”协作”部分,放上消息:
button sends comeGetMe message to elevator
建立这些项目时,可以增加对象的属性和行为。
完成这个实验室练习后,就有了实现电梯模拟程序的完整类清单。对每个类,有了完整的属性和行为清单以及对象之间要发送的消息清单。
下一章要开始介绍C++面向对象编程,介绍如何生成新类。学习第6章之后,就可以用C++编写电梯模拟程序的重要部分;学习第7章和第8章之后,就可以实现可运行的电梯模拟程序;学习第9章和第10章之后,就可以使用继承,利用类之间的共性减少解决问题所需的编程工作量。
下面小结第2章到第5章介绍的面向对象设计过程。
1.在文本文件中输人问题陈述。
2.放弃不重要的文本。
3.取出所有事实,在事实文件中每一行列出一个事实。
4.找出事实中的名词,其通常是需要的类,对每个类进行高度概括。
5.对每个事实,放在相应类中进行二级概述。如果一个事实涉及几个类,则放在涉及的每个类中。
6.组分类中的事实,列出属性、行为和协作。
7.在属性中,列出与每个类相关的数据。
8.在行为中.列出每个类对象收到消息时进行的操作。每个行为是类的成员函数,
9.在协作中,列出这个类对象向其他类对象发出的消息和接收该消息的类对象,
10.这时设计中可能还缺点什么,第6章介绍如何用C++实现电梯模拟程序时,这些问题会显露出来。
属性与行为通常称为类的“责任”。这里介绍的设计方法有时称为类、责任与协作(简单CRC)。
●指针变量的值为内存地址。
●下列声明:
int *ptr
声明变量ptr为int类型对象的指针,或者说成“ptr是int的指针”。声明为指针的每个变量前面都要加上星号(*)。
●指针可以初始化为0、NULL或一个地址。数值为0或NULL的指针不指任何内容。
●数值0是可以直接赋给指针变量的惟一整数值。
●&(地址)运算符返回操作数的地址。
●地址运算符的操作数必须是变量名,地址运算符不能用于常量、不产生引用的表达式和用存储类register声明的变量。
●*运算符通常称为间接运算符或复引用运算符。返回操作数(即指针)所指对象的同义词、别名或浑名。这种使用*的方法称为复引用指针。
●调用函数并要修改参数时,传递该参数地址。被调用函数使用间接运算符(*)修改调用函数中的参数值。
●接收地址参数的函数要定义接收地址的指针参数。
●不需要在函数原型中包括指针名,只要包括指针类型即可。参数名仅用于程序中的说明,编译器将其忽略。
●const限定符使程序员通知编译器,特定变量的值不能修改。
●如果试图修改const类型的值,则编译器会捕获这个错误并发出一个警告或错误消息(取决于特定的编译器)。
●将指针传递给函数有四种方法:非常量数据的非常量指针、非常量数据的常量指针、非常量数据的常量指针和常量数据的常量指针。
●数组自动用指针按引用传递,因为数组名的值为数组地址。
●要用指针按引用调用传递单个数组元素,就必须传递特定数组元素的地址。
●C++提供一元运算符sizeof,确定程序执行期间的数组长度或其他数据类型长度(字节数)。
●采用数组名时,sizeof运算符返回数组中的总字节数为size_t类型的值,通常是unsigned int 类型。
●sizeof运算符可以用于任何变量名、类型名或常量值。
●指针可以使用自增(++)或自减(--)运算符,整数可以加进指针中(+或+=),也可以从指针中减去整数(-或-=),指针可以减去另一指针。
●将指针增加或减去一个整数时,指针并不是直接增加或减去这个整数,而是加上指针所指对象长度的这个倍数。
●对相邻内存地址(如数组)进行指针算法时才有意义。数组中的所有元素在内存中是相邻存放的。
●对字符数组进行指针算法时,结果与普通算法相同,因为每个字符占一个字节内存。
●如果两个指针的类型相同,则可以将一个指针赋绐另一个指针。否则要用强制类型转换运算符将赋值浯句右边的指针值转换为赋值语句左边的指针值。这个规则的例外是void的指针(即void*),该指针是个一般性指针,可以表示任何指针类型。所有指针类型都可以赋给void指针而不需要进行强制类型转换。但是,void指针不能直接赋给另一类型的指针,而要先将void指针转换为正确的指针类型。
●void*指针不能复引用。
●指针可以用相等和关系运算符比较,但这种比较只在对相同数组成员进行时才有意义。
●指针也可以像数组一样带有下标。
●数组名等同于数组第一个元素的指针。
●指针/偏移量符号中的偏移量等同于数组下标。
●所有带下标的数组表达式都可以写成指针和偏移量,或是用数组名作为指针,或是用一个独立的指针指向数组。
●数组名实际上是个常量指针,总是指向数组开头的内存地址。
●数组可以包含指针。
●函数指针包含函数在内存中的地址。
●函数指针可以传入函数、从函数返回、存放在数组中和赋给其他的函数指针。
●函数指针的一个用法是建立菜单驱动系统,提示用户从菜单选择一个选项。
●函数strcpy将第二个参数(字符串)复制到第一个参数(字符数组)中,这个字符数组的长度应当足以放下字符串及其null终止符。
●函数stmcpy与strepy相似,只是stmcpy指定从字符串复制到字符数组的字符数。注意函数strncpy不一定复制第二个参数的null终止符,null终止符要在复制的字符数比字符串长度至少多1时才复制。
●函数strcat将第二个参数(字符串)添加到第一个参数(字符数组)中。第二个参数的第一个字符代替终止第一个参数中字符串的null终止符('\0')。程序员要保证存放第一个字符串的数组应足以存放第一个字符串和第二个字符串。
●函数strncat从第二个字符串添加指定字符数到第一个字符串中,并在结果中添加null终止符。
●函数strcmp一次一个字符地比较第一个字符串参数与第二十字符串参数。如果字符串相等,则函数返回0;如果第一个字符串小于第二个字符串,则函数返回负值;如果第一个字符串大于第二个字符串,则函数返回正值。