};
{ 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<<\ exit(1); } };
说明:Shape类给出了以后要定义的图形的公有特征。它用构造函数来设置颜色,并提供一个显示形状的虚函数Draw()。当图形不同时,Draw()的实现也有所不同(例如以半径和圆心作圆就与按长宽来作矩形不同)。基类只给出Draw()的调用形式,具体实现留给派生类。由于基类有一个语句exit(1),如果直接使用基类的Draw(),就要给出错误的信息。
从Shape类我们派生一个直线line类: class Line:public Shape {
private: point start,end; public: Line(ColorType c,point s,point e):Shape( c) { start=s; end=e; } virtual void Draw() { cout<<\ cout<<\。\ cout<<\。\ //这里可以加一些别的语句 } };
说明: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(c) { upperleft=ul; lowerright=lr; } virtual void Draw() { cout<<\ cout<<\。\ cout<<\。\ // 其他语句。 } };
class Circle:public Shape {
private:
point center; //圆心 int radius; //半径 public: Circle(ColorType c,point cent,int rad):Shape(c) { center=cent; radius=rad; } virtual void Draw() { cout<<\ cout<<\。\ cout<<\。\ //其他语句 } };
最后我们还要设计一个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文件中。 #include \void main() { Line l1(Red,point(1,1),point(250,300)); Line l2(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)。
5、实验思考
(1) 大家可以定义在Shape类的基础上定义一个椭圆类,尽量用最好的方式表现这个椭圆,并仿造上面的方法在虚函数Draw()中输出这个椭圆。
(2) 由于枚举数列只能表现数值,如本例中表现颜色时,只能出现数字,不能出现具体 的颜色,试编写一个函数,实现数字和颜色的转换,并把它在虚函数Draw()中表现出来。
(3) 本例是通过paint()函数里的for循环,一次性全部调用了6个类的虚函数,这只能针对本例而言,没有可移植性。大家可以在picture里再编写一个函数,可分别调用各个类的虚函数,要用上指针或引用。