南京邮电大学C++实验(一)类和对象的定义及使用(仅参考)

实验名称:类和对象的定义及使用

一、实验目的和要求

(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

参考实验教材中相应的实验指导,完成源程序代码如下:

//Test1—_h.h 定义BookCard类
#include<iostream>
#include<string.h>
using namespace std;
class BookCard
{
private:
    string id; //借书证的学生的学号
    string stuName;  //借书证学生的姓名
    int number;  //所借书的数量
public:
    BookCard(string a="B19010250", string b="雪峰", int c=4);
    //用来初始化3个数据成员,是否带默认参数值参考结果来分析
    void display();  //显示借书证的3 个数据成员的信息
    bool borrow(); //已借书数量不足10 则将数量加1,数量达到10 则直接返回false
};
//BookCard类成员函数
#include"1-1.h"
#include<iostream>
using namespace std;
BookCard::BookCard(string a, string b, int c) :id(a), stuName(b), number(c) 
//初始化列表初始化
{ }
void BookCard::display()
{
    cout << id << " " << stuName << " " << number << endl;
}
bool BookCard::borrow()
{
    if (number < 10)
    {
       number++;
       return true;
    }
    else
       return false;
}
//主程序
#include"Test1_h.h"
#include<iostream>
using namespace std;
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,有三个私有成员变量HourMinuteSecond,定义构造函数、析构函数以及用于改变、获取、输出时间信息的公有函数,主函数中定义时间对象,并通过调用各种成员函数完成时间的设定、改变、获取、输出等功能。

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

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

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

定义一个普通函数。

void f(Time  t)

{  

         t. PrintTime( );

}

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

参考实验教材中相应的实验指导完成程序,并回答相关问题。完成后的源程序代码如下:

#include<iostream>
using namespace std;
class Time
{
private:
    int Hour, Minute, Second;
public:
    Time(int h = 0, int m = 0, int s = 0);
    void Change(int h, int m, int s);
    int GetHour();
    int GetMinute();
    int GetSecond();
    void PrintTime();
    //void IncreaseOneSecond();
    ~Time();
};
Time::Time(int h, int m, int s)
{
    Hour = h;
    Minute = m;
    Second = s;
    cout << "Construct" << endl;
}
void Time::Change(int h, int m, int s)
{
    Hour = h;
    Minute = m;
    Second = s;
}
int Time::GetHour()//获取Hour
{
    return Hour;
}
int Time::GetMinute()//获取Minute
{
    return Minute;
}
int Time::GetSecond()//获取Second
{
    return Second;
}
void Time::PrintTime()
{
    cout << Hour << ":" << Minute << ":" << Second<< endl;
}
Time::~Time()
{
    cout << "Destructor:" << Hour << ":" << Minute << ":" << Second << endl;
}

int main()
{
    Time t1;
    Time t2(20);
    Time t3(20, 30);
    Time t4(20, 30, 56);
    t1.PrintTime();
    t2.PrintTime();
    t3.PrintTime();
    t4.PrintTime();
    t4.Change(23, 59, 59);
    t1.Change(14, 28, 12);
    cout << "ChangeTime" << t1.GetHour() << ":" << t1.GetMinute() << ":" << t1.GetSecond() << endl;
    cout << "ChangeTime" << t4.GetHour() << ":" << t4.GetMinute() << ":" << t4.GetSecond() << endl;

}

程序的运行结果是:

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

调用方式:自动调用

执行顺序:先执行构造函数,程序结束时执行析构函数。
析构函数的调用顺序与构造函数相反。

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

该函数的代码如下:

void Time::IncreaseOneSecond()
{
    if (Second < 59)
       Second++;
    else
    {
       Second = 0;
       if (Minute < 59)
           Minute++;
       else
       {
           Minute = 0;
           if (Hour < 23)
              Hour++;
           else
              Hour = 0;
       }
    }
}

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

f函数的原型主函数中调用f的语句

构造函数

调用次数

拷贝构造函数

调用次数

析构函数调用次数
void f(Time t);f(t1);112
void f(Time &t);f(t1);101
void f(Time *t);f(&t1);101

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

对象作为形式参数:

调用时,实参的值传给形参,要调用复制构造函数,且形参占内存空间,析构函数调用两次

对象引用作为形式参数:

相当于是实参的别名,就是对实参对象进行操作,形参不占内存空间,也不需要调用拷贝构造函数。

对象指针作形式参数:

不调用拷贝构造函数,通过指针可以访问实参对象的值,且未再次调用构造函数。

实验题目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="ABC",int A=18 );
    void Output();
    //void VisitBoy(Boy&);
    ~Girl()
    {
       cout << "Girl destructing" << endl;
    }
};
class Boy
{
private:
    string Name;
    int Age;
    //friend Girl;
public:
    Boy(string N = "ABC", int A = 18);
    void Output();
    //void VisitGirl(Girl&);
    ~Boy()
    {
       cout << "Boy destructing" << endl;
    }
};
Girl::Girl(string N , int A )
{
    Name = N;
    Age = A;
    cout << "Girl constructing" << endl;
}
void Girl::Output()
{
    cout << "Girl's name:" << Name << endl;
    cout << "Girl's age:" << Age << endl;
}
Boy::Boy(string N , int A )
{
    Name = N;
    Age = A;
    cout << "Boy constructing" << endl;
}
void Boy::Output()
{
    cout << "Boy's name:" << Name << endl;
    cout << "Boy's age:" << Age << endl;
}
int main()
{
    Girl g("Lm", 19);
    Boy b("Zs", 20);
    g.Output();
    b.Output();
}

程序的运行结果是:

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

void Girl::VisitBoy(Boy& boy)
{
    cout << "Boy's name:" << boy.Name << endl;
    cout << "Boy's age:" << boy.Age << endl;
}

程序的运行结果是:

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

友元关系是单向的,不具有交换性

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

int main()
{
    Girl g("Lm", 19);
    Boy b("Zs", 20);
    g.VisitBoy(b);
    b.VisitGirl(g);
    b.Output();
    g.Output();
}

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

void VisitBoyGirl(Boy& boy, Girl& girl)
{
    cout << "Boy's name:" << boy.Name << endl;
    cout << "Boy's age:" << boy.Age << endl;
    cout << "Girl's name:" << girl.Name << endl;
    cout << "Girl's age:" << girl.Age << endl;
}
int main()
{
    Girl g("Lm", 19);
    Boy b("Zs", 20);
    VisitBoyGirl(b, g);
}

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

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

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

错误提示信息:

不能接受0个参数,没有重载函数接受两个参数

原因:

实际参数个数不能少于无默认值的形式参数个数

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

错误提示信息:

没有与参数列表匹配的构造函数

原因:

系统默认的构造函数无形式参数

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

错误提示信息:

Time::Hour无法访问private成员、Time::Minute无法访问private成员Time::Second无法访问private成员

结果:

成功运行

    4.其它问题及解决办法

问题:函数声明时指定默认参数后,函数首部再次指定

方法:删除函数首部的默认值,只保留形参

(二)实验心得

       通过本次实验,进一步熟悉了类的定义以及成员函数的使用,同时通过题目2和题目3对于publicprivate属性有了更深的体会。同时,掌握了关于构造函数和析构函数的调用方式和调用顺序的异同,以及不同形式对象做形式参数时,两者调用的情况和背后的原因。

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

  • 50
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,以下是我提供的代码: ```c++ #include <iostream> #include <string> using namespace std; class Employee { protected: string name; int age; public: Employee(string name, int age) { this->name = name; this->age = age; } virtual void display() { cout << "Name: " << name << endl; cout << "Age: " << age << endl; } }; class Manager : public Employee { private: int department; public: Manager(string name, int age, int department) : Employee(name, age) { this->department = department; } void display() { cout << "Name: " << name << endl; cout << "Age: " << age << endl; cout << "Department: " << department << endl; } }; class Salesman : public Employee { private: int sales; public: Salesman(string name, int age, int sales) : Employee(name, age) { this->sales = sales; } void display() { cout << "Name: " << name << endl; cout << "Age: " << age << endl; cout << "Sales: " << sales << endl; } }; class SalesManager : public Manager, public Salesman { public: SalesManager(string name, int age, int department, int sales) : Manager(name, age, department), Salesman(name, age, sales) {} void display() { cout << "Name: " << name << endl; cout << "Age: " << age << endl; cout << "Department: " << department << endl; cout << "Sales: " << sales << endl; } }; int main() { Employee* e = new Employee("Tom", 25); e->display(); cout << endl; Manager* m = new Manager("Jerry", 30, 101); m->display(); cout << endl; Salesman* s = new Salesman("Lucy", 28, 100000); s->display(); cout << endl; SalesManager* sm = new SalesManager("Bob", 35, 102, 200000); sm->display(); cout << endl; return 0; } ``` 解释一下:我们定义了一个 `Employee` 类,表示员工,包含姓名和年龄两个属性,以及一个 `display()` 方法用于显示员工信息。然后派生出 `Manager` 类和 `Salesman` 类,分别表示经理和销售员,这两个类在 `Employee` 类的基础上增加了一些属性,分别为部门和销售额,同时也重载了 `display()` 方法。最后,我们再派生出 `SalesManager` 类,表示销售经理,这个类同时继承了 `Manager` 和 `Salesman` 两个类,因此可以直接使用它们的属性和方法。在 `main()` 函数中,我们分别创建了一个 `Employee` 对象、一个 `Manager` 对象、一个 `Salesman` 对象和一个 `SalesManager` 对象,然后都调用了它们的 `display()` 方法来展示各自的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鲤鱼Louis

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

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

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

打赏作者

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

抵扣说明:

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

余额充值