实验10类与对象1(2)
请将自己报告部分,文字和程序代码,加粗
完成下面实验内容和实验要求。
自测练习
1.实验10自测题2
⑴ 定义一个书籍类Book,其成员数据包括名称name、作者author、出版社press和页数numberOfPages。实现一个打印自身信息的内联成员函数printBook(),将修改出版社的函数setPress()实现为带默认参数值的函数,默认的参数为”清华大学出版社”。生成一个出版社为”高等教育出版社”的Book对象,调用setPress()成员函数将出版社修改为”清华大学出版社”,调用printBook()成员函数打印修改出版社前后的对象信息。
⑵ 要求
给出缺省构造函数和带所有成员数据的构造函数 ⑶ 思路
参考教材中“类的成员函数为带默认参数值的函数和内联成员函数”的相关代码 ⑷将下面程序代码补充完整,并运行
#include
class Book
{ // 类Book的定义 public: Book();// 显式的默认构造函数 Book(char* pName, char* pAuthor, char* pPess, int pNumberOfpages); // 带参数构造函数
void printBook();
// 隐式内联函数 void setPress(char* pPress = \清华大学出版社\
{
if (press != 0)
delete[] press;
press = new char[strlen(pPress) + 1]; if (press != 0) strcpy(press, pPress);
} ~Book(); private:
1
char* name; char* author; char* press; // 三个野指针 int numberofpages; };
Book::Book() {
// 显式默认构造函数用来创建和初始化对象(一般情况下,指针初始化为NULL,int,float,double,char等初始化为0,对象成员初始化,如string,#include
numberofpages = 0; //Book缺省构造函数的实现 cout << \}
Book::Book(char* pName, char* pAuthor, char* pPress, int pNumberOfPages) { // Book带所有成员数据的构造函数的实现 name = new char[strlen(pName) + 1]; if (name != 0) strcpy(name, pName); author = new char[strlen(pAuthor) + 1]; if (author != 0) strcpy(author, pAuthor); press = new char[strlen(pPress) + 1]; if (press != 0) strcpy(press, pPress); numberofpages = pNumberOfPages; cout << \}
inline void Book::printBook() // 显式内联函数 { // Book内联成员函数printBook的实现 cout << \ << \ << \ << \ << \}
2
void Book::setPress(char* pPress = \清华大学出版社\{ // Book成员函数setPress的实现 if (press != 0)
delete[] press; // 这个if条件句保证释放掉之前press指向的堆区
// 指针!=0相当于指针!=NULL,0是唯一一个可以跟指针比较的数,为什么要有[],new的时候有[],delete的时候也加上[],如果是基本类型的指针比如int,char,可以用delete或者delete[],但是如果是对象数组必须使用delete[],不然只会析构第一个对象,如Book *b = new Book[2];用delete[] b可以析构b[0]和b[1];如果用delete b只会析构b[0],习惯上new对应delete,new[]对应delete[]。
press = new char[strlen(pPress) + 1]; if (press != 0) strcpy(press, pPress); }
Book::~Book() { delete[] name; delete[] author; delete[] press; name = NULL; author = NULL; press = NULL;
// 同样的指针指向的区域释放完成之后也将指针本身置为NULL,防止产生野指针。指针本身同int,char一样是一种数据类型,存放在栈区,由操作系统负责释放,所以Book的成员numberofpages不需要手动释放,同样name,author和press指针本身也不需要手动释放。 cout << \}
int main() { Book bk(\微机原理与接口技术\姚琳\高等教育出版社\ bk.printBook(); bk.setPress(); bk.printBook(); return 0;
// 程序结束之后Book对象bk在操作系统作用下自动释放,调用析构函数,手动申请的内存区域,同样Book的成员numberofpages以及name,author和press三个指针本身也在操作系统作用下自动释放,如果使用Book *b=new Book(\微机原理与接口技术\\姚琳\高等教育出版社\,还需要手动调用delete b;
// 所以对大型工程来说,大量的内存泄露会影响运行效率,但是当程序运行结束之后操作系统会收回所有由该程序申请的空间,包括堆区和栈区。对于该程序来说,只要点击
3
DOS黑框的‘X’号,就会收回所有申请的空间。
} ⑸ 运行结果
(1)野指针与空指针 (2)隐式内联函数
(3)显式的默认构造函数及其作用 (4)指针本身的属性 (5)NULL (6)指针!=0
(7)delete和delete[] (8)栈区和堆区
(9)手动释放与自动释放 (10)释放的时机
⑹ 思考题及问题
考虑如何将内联成员函数setPress实现为另外一种形式(不使用关键字inline)? 答:采用隐式内联函数,即在类的定义中写出内联语句,不使用函数声明的形式。
2.实验10自测题3
⑴ 定义一个工程师类Engineer,其成员数据包括编号id、姓名name和职称position,实现一个打印自身信息的成员函数printEngineer(),定义一个包含4个工程师对象的对象数组,并使用new运算符申请两个匿名对象。调用printEngineer()打印所有对象的信息。
⑵ 要求
给出Engineer类的构造函数和析构函数
4
⑶ 思路
参考实验10练习题3及教材中“对象数组和对象指针”的相关代码 ⑷将下面程序代码补充完整,并运行
#include
Engineer::Engineer() { id = 0; name = NULL; position = NULL; cout << \}
Engineer::Engineer(int pId, char* pName, char* pPosition) { //Engineer的构造函数的实现 id = pId; name = new char[strlen(pName) + 1]; if (name != 0) strcpy(name, pName); position = new char[strlen(pPosition) + 1]; if (position != 0) strcpy(position, pPosition); }
void Engineer::setEngineer(int pId, char* pName, char* pPosition) { //Engineer的成员函数setEngineer的实现 id = pId; name = new char[strlen(pName) + 1];
5