实验2 类和对象(4学时) 1.实验目的
2.1.学习类与对象的定义。 2.2.掌握类与对象的使用方法。 2.3.学习类和对象的声明。
2.4.学习具有不同属性的数据成员与成员函数的访问方式。 2.5.理解构造函数和析构函数的定义与执行过程。 2.6.学会类的聚集使用方法。
2.7.理解静态数据成员和静态成员函数的含义。 2.8.理解什么是运算符重载,掌握运算符重载的方法。
2.实验类型
设计型。
3.实验基本要求
2.1. 下面是“平面上点”类的定义:
class CPoint {
private: int x, y; static int nCount; // nCount用于保存点的个数 public: CPoint(int px=0, int py=0); CPoint(CPoint&); ~CPoint(); int GetX(); int GetY(); void SetX(int); void SetY(int); void ShowPoint(); };
请完成该类中各成员函数的定义。 2.2. 下面是“平面上线段”类的定义: class CLine
{
private: CPoint pt1, pt2; //pt1和pt2分别代表该线段的起点和终点 public: CLine(); CLine(int x1,int y1,int x2,int y2); CLine(CPoint p1,CPoint p2); double Distance(); //计算该线段长度的成员函数 void ShowLine(); };
请完成该类中各成员函数的定义。并利用VC调试工具观察含有组合关系类的构造函数和析构函数的执行情况。
2.3. 以成员函数的方式,重载题目1中的CPoint类的“+”运算符,返回的CPoint类对象的横纵坐标值分别等于原两点的横纵坐标值之和;以全局函数的方式重载CPoint类的“-”运算符,返回的CPoint类对象的横纵坐标值分别等于原两点的横纵坐标值之差。
2.4. 对于题目1中的CPoint类,重载“>>”运算符使得像cin等输入流对象能够写CPoint类对象,再重载“<<”运算符使得像cout等输出流对象能够输出CPoint类对象。
4.实验基本步骤
2.1. 该类是一个基本的类。在编写该类时,要注意对静态成员nCount的操作,使其能
够正确表示程序中点的个数。编完该类后,要在main()函数中进行测试,分别定义CPoint类的对象、指针、引用,对各成员函数进行调用。分析对静态成员的调用和一般成员的调用方式有什么不同。
2.2. 要思考如何对类中3个构造函数CLine(),CLine(int x1,int y1,int x2,int y2)和
CLine(CPoint p1,CPoint p2);的编写,分析什么是初始化列表。完成后要在main()中进行测试。
2.3. 以成员函数方式重载的“+”操作符的原型为:CPoint CPoint::operator+ (CPoint pt);
以全局函数方式重载的“-”操作符的原型为:CPoint operator- (CPoint pt1, CPoint pt2); 分析以成员函数方式和全局函数方式重载运行符的异同点。
2.4. 重载的“>>”操作符的原型为:istream& operator>>(istream&, CPoint&);重载的“<<”
操作符的原型为:ostream& operator>>(ostream&, CPoint);思考一下,重载的“>>”操作符和“<<”操作符能否作为CPoint类的成员函数来实现。
5.实验思考题
2.1. 类和结构体的区别是什么?
结构体定义中默认情况下的成员是public,而类定义中的默认情况下的成员是private的。类中的非static成员函数有this指针,类的关键字class能作为template模板的关键字 即template
2.2. 类的成员函数与普通的函数有何区别?
普通函数一般有两种传递方式,按类型传递和按值传递,也就是传指针和传返回值两种情况。成员函数一般是按类型传递,也即是传指针地址。
普通函数可以随便调用,并且无法继承和封装,成员函数根据类的不同,可以进行继承,根据公有私有的不同,调用方式也不同。
2.3. 构造函数和析构函数的作用是什么?
构造函数只是起初始化值的作用,但实例化一个对象的时候,可以通过实例去传递参数,从主函数传递到其他的函数里面。
析构函数与构造函数的作用相反,用于撤销对象的一些特殊任务处理,可以是释放对象分配的内存空间。
2.4. 类的访问控制权限有何意义?
让使用者无法碰触到他们不该碰触的东西。这些东西仅供类的内部机制使用。将某些成员声明成private,对于使用者来说降低了对使用对象认识的难度。
让程序设计者可以更动class内部运作方式,而无须担心波及到客户端程序。
实验3 继承与多态(4学时) 1.实验目的
3.1. 学习定义和使用类的继承关系,定义派生类。 3.2. 熟悉不同继承方式下对基类成员的访问控制。 3.3. 学习使用虚函数实现动态多态性。 3.4. 学习利用虚基类解决二义性问题。
2.实验类型
设计型。
3.实验基本要求
3.1. 使用实验2中的CPoint类,定义 “空间中点”类如下: class CThreePoint:public CPoint {
private: int z; public: CThreePoint(); CThreePoint(int, int, int); int GetZ(); void SetZ(int pz); virtual void ShowPoint(); };
请完成该类中各成员函数的定义。并利用VC调试工具观察含有继承关系类的构造函数和析构函数的执行情况。分析为什么要把ShowPoint()函数设置为虚函数?有什么作用?请在main()函数中做测试。
3.2. 下面是一个“Shape”基类的定义:
enum ColorType{White, Black, Red, Green, Blue, Yellow, Magenta, Cyan}; //为图形形状定义Shape基类 class Shape {
protected:
ColorType color; public:
Shape(ColorType c); virtual void draw(); };
使用Shape类和CPoint类设计一个可在屏幕上作图的简单实例,要求是不必真正在屏幕上实现作图,只是有一个示意即可。例如:画一个矩形,不必真正画出矩形,只需输出一句话:“This is a rectangle!”即可。要求可画线段、矩形和圆形。要用到继承,虚函数,多态,数据的封装,构造函数的实现等等各种面向对象程序设计的特性。
3.3. 定义一个车(vehicle)基类,具有MaxSpeed、Weight等成员变量,Run、Stop等成员函数,由此派生出自行车(bicycle)类、汽车(motorcar)类。自行车(bicycle)类有高度(Height)等属性,汽车(motorcar)类有座位数(SeatNum)等属性。从bicycle和motorcar派生出摩托车(motorcycle)类,它们都有Run、Stop等成员函数。观察虚函数的作用。在继承过程中,注意把vehicle设置为虚基类。如果不把vehicle设置为虚基类,会有什么问题?编程试试看。
4.实验基本步骤
3.1. 编程时重点分析CThreePoint类的构造函数如何编写,并通过调试运行查看在继承关系中构造函数的执行顺序。
3.2. 可以使用CPoint类,指明屏幕上特定点的位置,其他的各个类都可以使用它。再使用基类Shape类,然后在Shpae类的基础上派生出各种类,如直线类Cline(可简单修改一下实验2中的Cline类),矩形类CRectangle,圆类CCircle。注意要把每个类的特征用最简单的方式表示出来。
3.3. 编写程序定义一个车(vehicle)基类,有Run、Stop等成员函数,由此派生出自行车(bicycle),汽车(motorcar),从bicycle和motorcar派生出摩托车(motorcycle),它们都有Run、Stop等成员函数。在main ( )函数中定义vehicle,bicycle,motorcar,motorcycle的对象,调用其Run()、Stop()函数,观察其执行情况。再分别用vehicle类型的指针来调用这几个对象的成员函数,看看能否成功;把Run、Stop定义为虚函数,再试试看。
5.实验思考题
3.1. C++中有哪几种派生方式?每种方式的派生类对基类成员的继承和访问控制属性
是什么样的?
三种派生方式:public,private,protected派生
public派生,在派生类里和外面都可以直接调用基类的公有部分。
protected保护派生,在派生类里可以直接调用,但是在派生外面不可以调用。 private私有派生,在派生类里和外面都不可以直接调用,但可以用函数间接调用。