Освой самостоятельно С++ за 21 день.
Шрифт:
Тем не менее все же иногда возникает необходимость выполнения чистой виртуальной функции. Она может быть вызвана из объекта, произведенного от ADT, например чтобы обеспечить общую функциональность для всех замещенных функций. В листинге 13.9 представлен видоизмененный листинг 13.7, в котором класс Shape объявлен как ADT и в программе выполняется чистая виртуальная функция Draw. Функция замещается в классе Circle, что необходимо для создания объекта
В данном примере дополнительная функциональность состоит в выведении на экран простого сообщения. В реальной программе чистая виртуальная функция может содержать достаточно сложный программный код, например создание окна, в котором рисуются все фигуры, выбираемые пользователем.
Листинг 13.9. Выполнение чистых виртуальных функций
1: // Выполнение чистых виртуальных функций
2:
3: #include <iostream.h>
4:
5: class Shape
6: {
7: public:
8: Shape{ }
9: virtual ~Shape{ }
10: virtual long GetArea = 0;
11: virtual long GetPerim= 0;
12: virtual void Draw = 0;
13: private:
14: };
15:
16: void Shape::Draw
17: {
18: cout << "Abstract drawing mechanism!\n";
19: }
20:
21: class Circle : public Shape
22: {
23: public:
24: Circle(int radius):itsRadius(radius) { }
25: virtual ~Circle { }
26: long GetArea { return 3 * itsRadius * itsRadius; }
27: long GetPerim { return 9 * itsRadius; }
28: void Draw;
29: private:
30: int itsRadius;
31: int itsCircumference;
32: };
33:
34: voidCircle::Draw
35: {
36: cout << "Circle drawing routine here!\n";
37: Shape::Draw;
38: }
39:
40:
41: class Rectangle : public Shape
42: {
43: public:
44: Rectangle(int len, int width):
45: itsLength(len), itsWidth(width){ }
46: virtual ~Rectangle{ }
47: long GetArea { return itsLength * itsWidth; }
48: long GetPerim { return 2*itsLength + 2*itsWidth;
49: virtual int GetLength { return itsLength; >
50: virtual int GetWidth { return itsWidth; }
51: void Draw;
52: private:
53: int itsWidth;
54: int itsLength;
55: };
56:
57: void Rectangle::Draw
58: {
59: for (int i = 0; i<itsLength; i++)
60: {
61: for (int j = 0; j<itsWidth; j++)
62: cout << "x ";
63:
64: cout << "\n";
65: }
66: Shape::Draw;
67: }
68:
69:
70: class Square : public Rectangle
71: {
72: public:
73: Square(int len);
74: Square(int len, int width);
75: virtual ~Square{ }
76: long GetPerim { return 4 * GetLength;}
77: };
78:
79: Square::Square(int len):
80: Rectangle(len,len)
81: { }
82:
83: Square::Square(int len, int width):
84: Rectangle(len,width)
85:
86: {
87: if (GetLength != GetWidth)
88: cout << "Error, not a square... a Rectangle??\n";
89: }
90:
91: int main
92: {
93: int choice;
94: bool fQuit = false;
95: Shape * sp;
96:
97: while (1)
98: {
99: cout << "(1)Circle (2)Rectangle (3)Square (0)Quit: ";
100: cin >> choice;
101:
102: switch (choice)
103: {
104: case 1: sp = new Circle(5);
105: break;
106: case 2: sp = new Rectangle(4,6);
107: break;
108: case 3; sp = new Square (5);
109: break;
110: default: fQuit = true;
111: break;
112: }
113: if (fQuit)
114: break;
115:
116: sp->Draw;
117: delete sp;
118: cout << "\n";
119: }
120: return 0;
121: }
Результат:
(1)Circle (2)Rectangle (3)Square (0)Quit: 2
x x x x x x
x x x x x x
x x x x x x
X X X Х X X
Abstract drawing mechanism!
(1)Circle (2)Rectangle (3)Square (0)Quit: 3
x x x x x
X X X X X
X X X X X
X X X X X
X X X X X
Abstract drawing mechanism!
(1)Circle (2)Rectangle (3)Square (0)Quit: 0
Анализ: В строках 5—14 объявляется класс абстрактного типа данных Shape с тремя чистыми виртуальными функциями. Впрочем, для того чтобы класс стал ADT, достаточно было объявить в нем хотя бы один из методов как чистую виртуальную функцию.