《面向对象程序设计》实验指导书
来源: 发布时间:2006-5-29 17:01:26 点击:
 
别调用他们的成员虚函数picture类。注意要把每个类的特征用最简单的方式表示出来。这个实验是一个很
综合的编程设计,希望大家先自己考虑考虑,可以参考第一个实验中的一些设计思想。
实验源代码:
程序的头文件我们放在graphic.h中   
//定义point类
#include <iostream.h>
#include <conio.h>
#include <math.h>
class point
{
private:
int x,y;
public;
point()
{
x=0;
y=0;   }
point(int x_pos,int y_pos)
{
x=x_pos;
y=y_pos;   }
point(const Point &p)
{
x=p.x;
y=p.y;    }
int getx()
{
return x;  }
int gety()
{
return y;  }
};
说明:类point包含了两个定义点的基本元素x坐标和y坐标,还有两个获得各坐标的成员函数getx()和
gety()。它的构造函数有三个,分别实现不同的功能。point()是给点赋0值。由于没有开辟内存,所以析构
函数可以没有。
//这是一个枚举,white至cyan分别代
//表了0至7的值
enum ColorType{White,Black,Red,Green,Blue
             Yellow,Magenta,Cyan};
//为图形形状定义Shape基类
class  Shape
{
protected:
ColorType  color;
public:
Shape(ColorType c)
{
color=c;
}
virtual void draw();
{
 cout<<"Draw not overridden"<<endl;
 exit(1);
}
};
说明:  Shape类给出了以后要定义的图形的公有特征。它用构造函数来设置颜色,并提供一个显示形状
的虚函数Draw()。当图形不同时,Draw()的实现也有所不同(例如以半径和圆心作圆就与按长宽来作矩形
不同)。基类只给出Draw()的调用形式,具体实现留给派生类。由于基类有一个语句exit(1),如果直接使用
基类的Draw(),就要给出错误的信息。
 从Shape类我们派生一个直线line类:
class  Line
{
private:
point   start,end;
public:
Line(ColorType c,point s,point e):
Shape(ColorType c)
{
start=s;
end=e;    }
virtual  void draw()
{
cout<<"This is a line!"<<endl;
cout<<"Its start point is ("
<<start.x<<","<<start.y<<
")。"<<endl;
cout<<"Its end point is ("
<<end.x<<","<<end.y<<
")。"<<endl;
 //这里可以加一些别的语句 
}
};
说明:Line包含两个定义起点和终止点的数据成员。它的构造函数接收两个点并把它赋给start和end成员
的point,还通过成员列表的形式接收一个传给基类Shape构造函数的颜色值。Line必须再次定义Draw(),
这里只给出了示意语句,大家可以通过调用图形库函数来完成画线、画矩形和画圆的功能,这里就不详细
述说了。
下面定义的Rectangle类和Circle类与Line类是类似的,它们都定义了几个数据成员、构造函数和虚
函数Draw()。
class Rectangle:public Shape
{
private:
point upperleft;
point lowerright;
public:
Rectangle(ColorType c,point ul,point lr)
:Shape(ColorType c)
{
   upperleft=ul;
   lowerright=lr;
}
virtual void Draw()
{
 cout<<"This is a rectangle!"<<endl;
cout<<"Its upperleft point is ("<<
   upperleft.x<<","<<upperleft.y<<
  ")。"<<endl;
cout<<"Its lowerright point is ("<<
   lowerright.x<<","<<lowerright.y<<
  ")。"<<endl;
 // 其他语句。
}
};

class Circle:public Shape
{
private:
point center; //圆心
int radius;  //半径
public:
Circle(ColorType c,point cent,int rad)
    :Shape(ColorType c)
{
   center=cent;
   radius=rad;   }
virtual void Draw()
{
cout<<"This is a circle!"<<endl;
cout<<"Its center is ("<<
    center.x<<","<<center.y
    <<")。"<<endl;
cout<<"Its radius is "<<radius
   <<"。"<<endl;
//其他语句 
}
};
最后我们还要设计一个Picture类,用来绘制这些图形
class Picture
{
private:
 Shape *s[6];
public:
 Picture(Shape* s1, Shape* s2 Shape* s3,
Shape* s4, Shape* s5 Shape* s6)
       {
          s[0]=s1;s[1]=s2;s[2]=s3;
          s[3]=s4;s[4]=s5;s[5]=s6;   }
       void  paint()
       {
          for(int i=0;i<6;i++)
          s[i]->Draw();   }
};
说明:Picture类中包含了6个Shape指针的数组、一个构造函数和一个显示六个形状的paint()
函数。由于Draw()定义为虚函数,所以paint()在调用Draw()时,并不关心Draw()是由什么形状
的类来调用的,它只是要把这6个图形一一画出就可以了。
下面给出主程序,主程序我们放在graphic.cpp文件中。
void main()
{
Line l1(Red,point(1,1),point(250,300));
Line l1(White,point(3,5),point(100,200));
//定义了两条红、白直线
Circle c1(Blue,point(100,75),50);
Circle c2(Green,point(50,200),20);
    //定义两个圆
Rectangle r1(Yellow,point(10,10),point(255,150));
Rectangle
r2(Magenta,point(20,30),point (100,125));
//定义两个矩形  
Picture  p(&l1,&l2,&c1,&c2,&r1,&r2);
p.paint();
}
说明:在程序中,我们生成了六个不同的图形对象,并把它传给了Picture对象的数组,当p调
用paint()方法时,也就通过for语句为每一个形状调用了Draw()方法。
最后的输出结果为:
This is a line!
Its start point is (1,1)。
Its end point is (250,300)。
This is a line!
Its start point is (3,5)。
Its end point is (100,200)。

This is a circle!
Its center is (100,75)。
Its radius is 50。
This is a circle!
Its center is (50,200)。
Its radius is 20。

This is a rectangle!
Its upperleft point is (10,10)。
Its lowerright point is (255,150)。
This is a rectangle!
Its upperleft point is (20,30)。
Its lowerright point is (100,125)。
实验思考:
(1) 大家可以定义在Shape类的基础上定义一个椭圆类,尽量用最好的方式表现这个椭
圆,并仿造上面的方法在虚函数Draw()中输出这个椭圆。
(2) 由于枚举数列只能表现数值,如本例中表现颜色时,只能出现数字,不能出现具体
的颜色,试编写一个函数,实现数字和颜色的转换,并把它在虚函数Draw()中表现
出来。
(3) 本例是通过paint()函数里的for循环,一次性全部调用了6个类的虚函数,这只能针对
本例而言,没有可移植性。大家可以在picture里再编写一个函数,可分别调用各个类的虚函数,
要用上指针或引用。

本新闻共3页,当前在第3页  1  2  3