《C++程序设计》实验报告(二)之简单类的设计与实现

一、实验目的:

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.

分析与讨论:

  1. 什么是封装?类是如何进行封装的?

答:

封装就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。C++通过类来实现封装性,把数据和与这些数据有关的操作封装在一个类中,或 者说,类的作用是把数据和算法封装在用户声明的抽象数据类型中,在声明了一个类以后,用户主要是通过调用公用的成员函数来实现类提供的功能

  1. 类的成员函数与普通的函数最本质的区别是什么?

答:

(1).静态成员函数实际上是一个全局函数,不依赖一个类的对象而属于类,不创建对象也可调用,静态成员函数没有this指针。而普通成员函数依赖一个类的对象,也就是它有一个隐藏的调用参数(this)指针,必须指向一个类的对象。

(2).静态函数只能访问类中的静态成员变量;

(3).如果成员函数想作为回调函数来使用,如创建线程等,一般只能将它定义为静态成员函数才行。

  1. 构造函数如何命名?析构函数如何命名?

答:构造函数是在初始化时可直接使用类调用,析构函数的命名只能在构造函数(类名)的前面加上“~” (英文型)符号

  1. 构造函数和析构函数的作用是什么?

答:

(1).构造函数的作用:用于新建对象的初始化工作。
(2).析构函数的作用:用于在撤销对象前,完成一些清理工作,比如:释放内存等。

  1. 什么时候需要自己定义构造函数和析构函数?

答:

每当创建对象时,需要添加初始化代码时,则需要定义自己的构造函数;而对象撤销时,需要自己添加清理工作的代码时,则需要定义自己的析构函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了一li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值