画面上の点を定義したので,今度は画面上の線を定義してみよう.
class Line {
protected:
vector2D p1; //始点
vector2D p2; //終点
int color;
public:
Line(int x1, int y1, int x2; int y2, int col) {
p1.x = x1; p1.y = y1; p2.x = x2; p2.y = y2;
color = col;
draw_line(x1,y1,x2,y2,color);
}
....
void move_to(int x, int y) { ... }
};
Line::move_to()は,線の始点を(x,y)に移動する関数だと
思ってほしい.
さて,MacDrawのようなグラフィックエディタを考えてみよう. このようなソフトでは,線・点などの図形を自由に移動したり 拡大・縮小したりできる.こんなときに,こういうクラスの定義をして おくと,何かと便利だ.
class GraphicObject {
public:
virtual void move_to(int,int) = 0;
};
class Point : public GraphicObject {
....
void move_to(int,int);
};
class Line : public GraphicObject {
....
void move_to(int,int);
};
GraphicObjectというクラスは,その下にあるPointやLine (や,この後作られるであろうRectancle, PolyLine, Ellipseなど) をひとまとめにして使うためのクラスで,それ自体はインスタンスを持たない. このようなクラスを抽象クラスと呼ぶ.
GraphicObjectを使った場合,前の方で出てきたMovingPointと
AccelPointのように,同じポインタに対してmove_to()
を呼ぶことで,それぞれの図形にあった動作をしてくれるというわけだ.
そのため,GraphicObjectはメンバ関数move_to()を
仮想関数として持たなければならないが,GraphicObject自体は
特定の図形ではないので,GraphicObject::move_to()を
定義することはできない.そこで,クラスGraphicObjectでは
関数の名前だけ定義して,その実装は派生クラスにまかせている.
これが
class GraphicObject {
public:
virtual void move_to(int,int) = 0;
};
という記述だ.このような関数を純粋仮想関数という.