南京邮电大学C++实验报告1

实 验 报 告

实验名称

类和对象的定义及使用  

实验类型

验证

实验学时

2

  • 实验目的和要求

(1)掌握类与对象的定义与使用方法,理解面向对象方法中通过对象间传递消息的工作机制。

(2)正确掌握类的不同属性成员的使用方法。

(3)掌握构造函数与析构函数的概念,理解构造函数与析构函数的执行过程。

(4)掌握友元函数和友元类的定义和使用。

(5)基本掌握指针和引用作为函数参数的应用。

二、实验环境(实验设备)

硬件:  微型计算机

软件:  Windows 操作系统、Microsoft Visual Studio 2010

三、实验原理及内容

 实验题目1 定义一个借书证类BookCard,在该类定义中包括如下内容。

(1)私有数据成员:

string id;          //借书证学生的学号

string stuName;    //借书证学生的姓名

int number;       //所借书的数量

(2)公有成员函数:

构造函数       //用来初始化3 个数据成员,是否带默认参数值参考结果来分析

void display()   //显示借书证的3 个数据成员的信息

bool borrow()   //已借书数量不足10 则将数量加1,数量达到10 则直接返回false

主函数及f()函数代码如下。请结合输出结果完成程序。

void f(BookCard &bk)

{

if (!bk.borrow())

{

bk.display();

cout<<"you have borrowed 10 books,can not borrow any more!"<<endl;

}

else

bk.display();

}

int main()

{

BookCard bk1("B20190620","东平",10),bk2;

f(bk1);

f(bk2);

return 0;

}

程序的运行结果为:

B20190620 东平 10

you have borrowed 10 books,can not borrow any more!

B19010250 雪峰 4

参考实验教材中相应的实验指导,完成源程序代码如下:中文五号宋体,英文五号Consolas字体,单倍行距)

#include<iostream>

#include<string>

using namespace std;

class BookCard{

private:

string id;

string stuName;

int number;

public:

BookCard(string id,string stuName,int number);

void display();

bool borrow();

};

BookCard::BookCard(string i="B19010250",string na="雪峰",int n=4)

{

id=i;stuName=na;number=n;

}

void BookCard::display()

{

cout<<id<<" "<<stuName<<" "<<number<<endl;

}

bool BookCard::borrow()

{

if(number<10&&number>0)

return 1;

else

return 0;

}

void f(BookCard &bk)

{

    if (!bk.borrow())

   {

       bk.display();

       cout<<"you have borrowed 10 books,can not borrow any more!"<<endl;

   }

    else

    bk.display();

}

int main()

{

    BookCard bk1("B20190620","东平",10),bk2;

    f(bk1);

    f(bk2);

    return 0;

}

实验题目2 定义一个时间类Time,有三个私有成员变量Hour、Minute、Second,定义构造函数、析构函数以及用于改变、获取、输出时间信息的公有函数,主函数中定义时间对象,并通过调用各种成员函数完成时间的设定、改变、获取、输出等功能。

 按要求完成类的定义与实现。

 修改数据成员的访问方式,观察编译结果。

 在Time类中定义一个成员函数,用于实现时间增加一秒的功能,主函数中通过对象调用该函数,并输出增加一秒后的时间信息。

 定义一个普通函数。

void f(Time  t)

{    t. PrintTime( );

}

在Time类中增加拷贝构造函数的定义,主函数中调用该函数,运用调试工具跟踪,分析整个程序调用构造函数(包括拷贝构造函数)和析构函数的次数;再将f函数的形式参数分别修改为引用参数和指针参数(此时函数代码修改为{t-> PrintTime( );},主函数中调用,再分析此时调用构造函数和析构函数的次数。

参考实验教材中相应的实验指导完成程序,并回答相关问题。完成后的源程序代码如下:中文五号宋体,英文五号Consolas字体,单倍行距)

 #include<iostream>

using namespace std;

class Time{

private:

int Hour;

int Minute;

int Second;

public:

Time(int h=0,int m=0,int s=0);

Time(const Time &ob);

~Time();

void change(int h,int m,int s);

int GetHour();

int GetMinute();

int GetSecond();

void PrintTime();

//void IncreaseOneSecond();

};

Time::Time(int h,int m,int s)

{

//cout<<"Constructing..."<<endl;

Hour=h;Minute=m;Second=s;

}

Time::Time(const Time &ob)

{

//cout<<"Copy constructing..."<<endl;

}

Time::~Time()

{

//cout<<"Destructing..."<<endl;

}

void Time::change(int h,int m,int s)

{

Hour=h;Minute=m;Second=s;

}

int Time::GetHour()

{

return Hour;

}

int Time::GetMinute()

{

return Minute;

}

int Time::GetSecond()

{

return Second;

}

void Time::PrintTime()

{

cout<<Hour<<"h"<<Minute<<"min"<<Second<<"s"<<endl;

}

/*void Time::IncreaseOneSecond()

{

     Second++;

 }*/

/*void f(Time  t)

{    t. PrintTime( );

}

*/

int main()

{

int h,m,s;

Time t1;

Time t2(6);

Time t3(6,7);

Time t4(6,7,8);

t1.PrintTime();

t2.PrintTime();

t3.PrintTime();

t4.PrintTime();

t1.change(11,12,13);

t2.change(11,12,13);

t3.change(11,12,13);

t4.change(11,12,13);

cout<<t1.GetHour()<<":"<<t1.GetMinute()<<":"<<t1.GetSecond()<<endl;

cout<<t2.GetHour()<<":"<<t2.GetMinute()<<":"<<t2.GetSecond()<<endl;

cout<<t3.GetHour()<<":"<<t3.GetMinute()<<":"<<t3.GetSecond()<<endl;

cout<<t4.GetHour()<<":"<<t4.GetMinute()<<":"<<t4.GetSecond()<<endl;

return 0;

}

程序的运行结果是:

0h0min0s

6h0min0s

6h7min0s

6h7min8s

11:12:13

11:12:13

11:12:13

11:12:13

构造函数与析构函数的调用方式及执行顺序是:

调用方式是自动调用,执行顺序是先执行构造函数,等程序结束再执行析构函数

析构函数的调用顺序与构造函数的调用顺序相反。

③取消类中成员函数IncreaceOneSecond( )的注释标志,将该函数补充完整,注意时间在增加一秒情况下的进位关系。

该函数的代码如下:中文五号宋体,英文五号Consolas字体,单倍行距)

void Time::IncreaseOneSecond()

{

     if(Second<59)

     {

      Second++;

 }

 else if(Second==59&&Minute==59&&Hour==23)

 {

  Hour=0;

  Minute =0;

  Second=0;

 }

 else if(Second==59&&Minute==59&&Hour<23)

 {

  Minute=0;

  Second=0;

  Hour++;

 }

 else if(Second==59&&Minute<59&&Hour<23)

 {

  Minute++;

  Second=0;

  Hour++;

 }

 cout<<Hour<<":"<<Minute<<":"<<Second<<endl;

 }

 主函数中定义一个Time类对象并调用一次f函数,观察结果填写下表:

f函数的原型

主函数中调用f的语句

构造函数

调用次数

拷贝构造函数调用次数

析构函数调用次数

void f(Time t);

    f(t0);    

      1     

      1    

      2    

void f(Time &t);

    f(t0);       

      1    

      0    

      1   

void f(Time *t);

    f(&t0);       

      1    

      0    

      1   

    通过以上结果,关于对象作形式参数、对象引用作形式参数、对象指针作形式参数时构造函数、析构函数的调用次数及顺序,你得到什么结论?

实验题目3 定义一个Girl类和一个Boy类,这两个类中都有表示姓名、年龄的私有成员变量,都要定义构造函数、析构函数、输出成员变量信息的公有成员函数。

根据要求定义相应的类。

将Girl类作为Boy类的友元类,在Girl类的成员函数VisitBoy(Boy & )中访问Boy类的私有成员,观察程序运行结果。

在Boy类的某成员函数VisitGirl(Girl & )中试图访问Girl类的私有成员,观察编译器给出的错误信息,理解原因。

主函数中正确定义两个类的对象,调用各自的成员函数实现相应功能。

再将Boy类作为Girl类的友元类,在Boy类的某成员函数VisitGirl(Girl & )中访问Girl类的私有成员,观察编译器给出的信息。

删除两个类中的函数VisitGirl(Girl & ) ,VisitBoy(Boy & ),定义一个顶层函数VisitBoyGirl(Boy &, Girl &),作为以上两个类的友元,通过调用该函数输出男孩和女孩的信息。

实验解答:

①定义相应的类,主函数中定义相应的类成员,调用各类的输出函数显示信息。

源程序代码如下:

#include<iostream>

#include<string>

using namespace std;

class Boy;

class Girl{

private:

string name;

int age;

public:

Girl(string n,int a);

~Girl()

{

cout<<"Girl destructing..."<<endl;

}

void print();

void VisitBoy(Boy &);

};

class Boy{

private:

string name;

int age;

//friend Girl;

public:

Boy(string n,int a);

~Boy()

{

cout<<"Boy destructing..."<<endl;

}

    void print();

void VisitGirl(Girl &);

};

Girl::Girl(string n,int a)

{

name=n;

age=a;

cout<<"Girl constructing..."<<endl;

}

void Girl::print()

{

cout<<"Girl's name:"<<name<<" age:"<<age<<endl;

 }

 void Girl::VisitBoy(Boy &boy)

 {

  cout<<"Boy's name:"<<name<<" age:"<<age<<endl;

 }

 Boy::Boy(string n,int a)

 {

  name=n;age=a;

  cout<<"Boy constructing..."<<endl;

 }

 void Boy::print()

 {

  cout<<"Boy's name:"<<name<<" age:"<<age<<endl;

 }

 void Boy::VisitGirl(Girl &girl)

 {

  cout<<"Girl's name:"<<name<<" age:"<<age<<endl;

 }

int main()

{

Girl a("fang",20);

Boy b("zhou",20);

a.VisitBoy(b);

a.print();

b.print();

}

程序的运行结果是:

Girl constructing...

Boy constructing...

Boy's name:fang age:20

Girl's name:fang age:20

Boy's name:zhou age:20

Boy destructing...

Girl destructing...

②将Girl类作为Boy类的友元类, 写出Girl类的成员函数VisitBoy(Boy & )的实现代码。

void Girl::VisitBoy(Boy &boy)

 {

  cout<<"Boy's name:"<<name<<" age:"<<age<<endl;

 }

程序的运行结果是:

Boy's name:zhou age:20

③在Boy类的某成员函数VisitGirl(Girl & )中试图访问Girl类的私有成员,记录编译器给出的错误信息,与②对比,你能得出友元的什么特性?

友元关系是单向的,不具有交换性,只有两个类都将对方声明为自己的友元才可互访。

④在上面代码的基础上,在Girl类的定义中,增加一行代码:friend  Boy; 在主函数中通过Boy类对象. VisitGirl(Girl类对象) 的形式输出Girl类对象的信息。编译的结果是什么?写出这一步你的主函数代码,要求分别用友元函数Girl类对象. VisitBoy(Boy类对象);Boy类对象. VisitGirl(Girl类对象) ;和输出两个类对象的信息。

a.VisitBoy(b);

b.VisitGirl(a);

a.print();

b.print();

Girl constructing...

Boy constructing...

Boy's name:fang age:20

Girl's name:zhou age:20

Girl's name:fang age:20

Boy's name:zhou age:20

Boy destructing...

Girl destructing...

⑤定义一个顶层函数void VisitBoyGirl(Boy &, Girl &),作为以上两个类的友元函数,主函数中通过调用该函数输出男孩和女孩的信息。写出该友元函数的完整代码,以及主函数的代码。

void VisitBoyGirl(Boy &boy, Girl &girl)

{

cout<<"Boy's name:"<<name<<" age:"<<age<<endl;

cout<<"Girl's name:"<<name<<" age:"<<age<<endl;

}

VisitBoyGirl(b,a);

四、实验小结(包括问题和解决方法心得体会、意见与建议等)

中文五号宋体,英文五号Consolas字体,单倍行距)

(一)实验中遇到的主要问题及解决方法

1.在题目2中不改变main()函数中的对象的定义方式,若取消构造函数中参数的默认值,编译程序错误提示信息及出错原因是:

error C2512: 'Time' : no appropriate default constructor available

函数二义性

2.在题目2中如果删除类中自定义的构造函数,仅使用系统默认构造函数,再编译,程序错误提示信息及出错原因是:

error C2512: 'Time' : no appropriate default constructor available

构造函数实参不正确

3.在题目2中如果将main()函数中的输出语句改为:cout<<对象名.Hour<<":"<<对象名.Minute<<":"<<对象名.Second<<endl; 重新编译,会出现什么错误提示?在这种情况下,如果将成员变量的访问属性修改为public再编译,结果如何?

error C2248: 'Time::Hour' : cannot access private member declared in class 'Time'

编译成功

    4.其它问题及解决办法

程序有点长,可以打草稿

(二)实验心得

多敲代码

(三)意见与建议(没有可省略)

建议多敲代码,注意区分析构函数和构造函数,注意无参和有参函数的区别

  • 10
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值