一、实验目的: 1.了解面向对象的程序设计的特点、思想,了解类的封装性和信息隐蔽。 2.掌握类和对象的定义和作用,熟练应用类和对象。 3.掌握类的成员函数的定义,熟练定义、应用类的成员函数。 4.掌握对象成员的引用,熟练应用对象成员的引用。 5.掌握构造函数、析构函数,要求熟练应用。 | |
二、实验内容 1.请检查下面程序,找出其中的错误,并改正之。然后上机调试,使之能正常运行。运行时从键盘输入时、分、秒的值,检查输出是否正确。 #include <iostream> using namespace std; class Time{ void set_time(void); void show_time(void); int hour; int minute; int sec; }; Time t; int main(){ set_time(); show_time(); } int set_time(void) { cin>>t.hour; cin>>t.minute; cin>>t.sec; } int show_time(void) { cout<<t.hour<<“:”<<t.minute<<“:”<<t.sec<<endl; } 2.运行程序 #include <iostream> using namespace std; class Student { public: Student(int n,float s):num(n),score(s){} void change(int n,float s){num=n;score=s;} void display(){cout<<num<<“ ”<<score<<endl;} private: int num; float score; }; int main() { Student stud(101,78.5); stud.display(); stud.change(101,80.5); stud.display(); return 0; } 要求: (1)分析其执行过程,写出输出结果。 (2)将main()第2行改为 const Student stud(101,78.5); 分析所修改部分的含义以及编译和运行的情况。 (3)将main()函数再改为: int main() { Student stud(101,78.5); Student *p=&stud; p->display(); p->change(101,80.5); p->display(); return 0; } 分析所修改部分的含义以及编译和运行的情况。 (4)在(3)的基础上将main函数第3行改为: const Student *p=&stud; 分析所修改部分的含义以及编译和运行的情况。 3.根据测试程序及测试程序的输出结果,编写类Welcome. (1)测试程序 void main() { Welcome we; Welcome you(we); you.display(); you.set(“Thank You.”); cout<<you.get()<<endl; you.talk(); you.display(); } (2)测试程序的输出结果 Welcome! Thank you. 输入:How are you? 输出:How are you? 输入:Fine,thank you. 输出:Fine,thank you. 输入:OK All Right! Goodbye! OK Goodbye! Goodbye! 程序: #include<iostream> #include<string.h> using namespace std; class Welcome { private: char sent[67]; public: Welcome() { set("Welcome!"); } ~Welcome() { set("Goodbye!"); Display(); } Welcome(Welcome& x) { set(x.Get()); } void Display() { cout << sent << endl; } void set(char* s) { strcpy(sent, s); } char* Get() { return sent; } void talk(); }; void Welcome::talk() { do { cout << "输入:"; gets(sent); if (strcmp(sent, "OK") == 0) { cout << "All right!" << endl; cout << "Goodbye!" << endl; break; } else { cout << "输出:" << sent << endl; } } while (1); } int main() { Welcome we; Welcome you(we); you.Display(); you.set("Thank you."); cout << you.Get() << endl; you.talk(); you.Display(); } 4.编写程序。编写一个复数类型complex,其中含有若干个成员函数,使用该类可以完成复数的加法,复数的输入输出。试完成该类定义并编写主函数,说明complex类对象,对定义的各成员函数进行调用。 实现方法: (1)complex类中数据成员可定义为private,实部变量为real,虚部变量为imag。 (2)可在complex类中声明两个构造函数,一个为无参构造函数,一个为有参构造函数,实现数据的录入功能。有参构造函数要使用参数初始化表对数据成员初始化。 (3)可在complex类中声明输出成员函数outCom(),而在类外定义成员函数。成员函数outCom()中要考虑到输出的虚部为负数和零的情况。 (4)在成员函数addCom()内,要对调用者对象与实参对象分别进行实部、虚部的加法运算,而后将所得到的结果(仍为一个complex类对象)作为函数值返回到调用函数中。 (5)在主函数中分别调用成员函数,实现复数的输入、加法、输出等功能。可编写如下样式的main()函数。 int main() { complex x(1,-2),y(3,4),sum; sum=x.addCom(y); x.outCom(); cout<<"+"; y.outCom(); cout<<"="; sum.outCom(); cout<<endl; return 0; } 程序: #include <iostream> using namespace std; class complex { public: complex() { } complex(int real, int imag) { this->real = real; this->imag = imag; } complex addCom(complex add) { complex sum; sum.real = this->real + add.real; sum.imag = this->imag + add.imag; return sum; } void outCom() { cout << this->real << " + " << this->imag << "i" << endl; } private: int real, imag; }; int main() { complex x(1, -2), y(3, 4), sum; sum = x.addCom(y); x.outCom(); cout << "+"; y.outCom(); cout << "="; sum.outCom(); cout << endl; return 0; } 5.编写程序。自定义一个简单的时间类TimeType,它具有数据成员h、m、s,用来表示当前时间的时、分、秒。而后设计该类欲实现的功能,进而设计出相应的类成员函数,实现对时分秒的增加、判断两个时间是否相等以及对时间的输出等操作。 试完成其各个成员函数,并编写主函数,说明TimeType类对象,对定义的各成员函数进行调用,以验证它们的正确性。 实现方法及要求: (1)通过自定义类TimeType,对“时间数据”进行各种所指定的处理。一个“时间数据”可通过“时、分、秒”来唯一确定,从而为该类设立私有数据成员h、m、s来表示这一数据。 由于要对“时间”进行多种不同的处理,进而设立不同的类成员函数来实现其各自的设定功能。 (2)对时间进行增加的成员函数可分别为incrementSec()、incrementMin()、incrementHou(),在定义这三个成员函数时要注意所谓“进位”处理:秒数超过60要“进位”到分,超过60分要“进位”到时,而超过24时后要“甩掉”24以上的部分等。 例如,秒数超过60则“进位”到分,可通过如下语句来实现: if(s>=60){m+=s/60;s=s%60;} 判断超过24时而后“甩掉”24以上的部分,则可使用语句: if(h>=24) h=h%24; (3)编写类似于如下样式的主函数,说明TimeType类对象,并通过类对象对TimeType类的各个成员函数进行调用,以验证每个成员函数的正确性。 void main() { TimeType t1(11,48,59),t2(11,59,48),t3; cout<<“t1=”; t1.printTime(); // printTime()实现时间的输出功能 cout<<“t2=”; t2.printTime(); cout<<“t3=”; t3.printTime(); if(t1.equal(t2)) cout<<“t1==t2”<<endl; else cout<<“t1!=t2”<<endl; t1.incrementMin(30); cout<<“‘t1.incrementMin(30);’=>”; cout<<“t1=”; t1.printTime(); …… } 程序: # include <iostream> using namespace std; class TimeType { private: int h, m, s; public: TimeType(int hO = 0, int mO = 0, int sO = 0); void incSec(int sec); void incMin(int min); void incHour(int hrs); bool equal(TimeType t2); void printTime(); }; TimeType::TimeType(int hO, int m0, int sO) { h = hO; m = m0; s = sO; } void TimeType :: incSec(int sec) { s = s + sec; m = m + s / 60; s = s % 60; h = h + m / 60; m = m % 60; } void TimeType :: incMin(int min) { m = m + min; h = h + m / 60; m = m % 60; } void TimeType::incHour(int hrs) { h = h + hrs; } bool TimeType::equal(TimeType t2) { int time1 = (h * 60 + m) * 60 + s; int time2 = (t2.h * 60 + t2.m) * 60 + t2.s; return time1 == time2 ? true : false; } void TimeType::printTime() { cout << "现在是:" << h << "时"; cout << m << "分"; cout << s << "秒" << endl; } int main() { TimeType t1(11, 48, 59), t2(11, 59, 48), t3; cout << "t1="; t1.printTime(); cout << "t2="; t2.printTime(); cout << "t3="; t3.printTime(); if (t1.equal(t2)) cout << "t1等于t2" << endl; else cout << "t1不等于t2" << endl; t1.incMin(30); cout << "t1="; t1.printTime(); } 6.编写程序。设计一个集合类Set,包括将集合置空、添加元素、判断元素是否在集合中、输出集合,以及将集合中元素逆置,另外还有一个拷贝构造函数,并使用一些数据进行测试。 实现方法: (1)Set类包括私有数据:elems(存放集合元素)、pc(当前元素指针,即集合元素的个数);Set类包括公有成员函数:一个默认构造函数和拷贝构造函数Set(set &s),另有成员函数empty()(将集合置空)、isempty()(判断集合是否为空)、ismemberof()(判断元素是否在集合中)、add()(添加元素)、print()(输出集合)、reverse()(将集合中元素逆置)。 (2)定义如下样式的主函数。 int main() { Set A; cout<<"A是否为空:"; cout<<A.isempty()<<endl; cout<<"A:"; A.print(); Set B; for(int i=1;i<=8;i++) B.add(i); cout<<"B:"; B.print(); cout<<"5是否在B中:"; cout<<B.ismemberof(5)<<endl; B.empty(); for(int j=11;j<20;j++) B.add(j); Set C(B); cout<<"C"; C.print(); C.reverse(); cout<<"C逆置"<<endl; cout<<"C:"; C.print(); return 0; } (3)在拷贝构造函数Set()中也可以使用对象的常引用做为形参。 程序: #include <iostream> using namespace std; class Set { public: Set() {} Set(const Set& s) { pc = s.pc; for (int i = 0; i < pc; i++) { elems[i] = s.elems[i]; } } string isempty() { if (pc == NULL) { return "是的"; } return "不是"; } void print() { if (pc == NULL) { cout << "空集" << endl; } else { for (int i = 0; i < pc; i++) { cout << elems[i] << "."; } } } void add(int e) { elems[this->pc] = e; this->pc++; } string ismemberof(int e) { for (int i = 0; i < pc; i++) { if (e == elems[i]) { return "在"; } } return "不在"; } void empty() { pc = 0; } void reverse() { int a[100]; for (int i = 0; i < pc; i++) { a[i] = elems[pc - 1 - i]; } for (int i = 0; i < pc; i++) { elems[i] = a[i]; } } private: int elems[100]; int pc = 0; }; int main() { Set A; cout << "A是否为空:"; cout << A.isempty() << endl; cout << "A:"; A.print(); Set B; for (int i = 1; i <= 8; i++) B.add(i); cout << "B:"; B.print(); cout << "5是否在B中:"; cout << B.ismemberof(5) << endl; B.empty(); for (int j = 11; j < 20; j++) B.add(j); Set C(B); cout << "C"; C.print(); C.reverse(); cout << "C逆置" << endl; cout << "C:"; C.print(); system("pause"); return 0; } 7.编写程序。设计一个点类Point,求两个点之间的距离。 实现方法: (1)可设计一个普通函数distance(Point &p1,Point &p2),用于计算点p1和p2之间的距离。 数据函数的库文件为:在原C中为math.h,在C++为math且使用名空间。 (2)定义如下样式的主函数。 void main() { Point p1(2,2),p2(5,5); p1.disp(); cout<<"与"; p2.disp(); cout<<"之间距离="<<distance(p1,p2)<<endl; } 程序: #include<iostream> #include<math.h> using namespace std; class Point { public: Point(int x, int y) :m_X(x), m_Y(y) {}//初始化列表赋值 void disp() { cout << "(" << m_X << "," << m_Y << ")" << endl; } int m_X, m_Y; }; float distance(Point a, Point b) { return sqrt(pow(a.m_X - b.m_X, 2) + pow(a.m_Y - b.m_Y, 2)); } void main() { Point p1(2, 2), p2(5, 5); p1.disp(); cout << "与"; p2.disp(); cout << "之间距离=" << distance(p1, p2) << endl; system("pause"); } | |
程序测试及运行结果: 1. 2. (更改main函数第二行) (更改main函数) 3. 4. 5. 6. 7. | |
分析与讨论:
答: 封装就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。C++通过类来实现封装性,把数据和与这些数据有关的操作封装在一个类中,或 者说,类的作用是把数据和算法封装在用户声明的抽象数据类型中,在声明了一个类以后,用户主要是通过调用公用的成员函数来实现类提供的功能
答: (1).静态成员函数实际上是一个全局函数,不依赖一个类的对象而属于类,不创建对象也可调用,静态成员函数没有this指针。而普通成员函数依赖一个类的对象,也就是它有一个隐藏的调用参数(this)指针,必须指向一个类的对象。 (2).静态函数只能访问类中的静态成员变量; (3).如果成员函数想作为回调函数来使用,如创建线程等,一般只能将它定义为静态成员函数才行。
答:构造函数是在初始化时可直接使用类调用,析构函数的命名只能在构造函数(类名)的前面加上“~” (英文型)符号
答: (1).构造函数的作用:用于新建对象的初始化工作。
答: 每当创建对象时,需要添加初始化代码时,则需要定义自己的构造函数;而对象撤销时,需要自己添加清理工作的代码时,则需要定义自己的析构函数。 |
《C++程序设计》实验报告(二)之简单类的设计与实现
于 2024-01-29 17:43:37 首次发布