Освой самостоятельно С++ за 21 день.
Шрифт:
66: Square(int len);
67: Square(int len, int width);
68: ~Square { }
69: long GetPerim { return 4 * GetLength;}
70: };
71:
72: Square::Square(int len):
73: Rectangle(len,len)
74: { }
75:
76: Square::Square(int len, int width):
77: Rectangle(len,width) 78:
79: {
80: if (GetLength != GetWidth)
81: cout << "Error, not a sguare... a Rectangle??\n";
82: }
83:
84: int main
85: {
86: int choice;
87: bool fQuit = false;
88: Shape * sp;
89:
90: while ( ! fQuit )
91: {
92: cout << "(1)Circle (2)Rectangle (3)Square (0)Quit:";
93: cin >> choice;
94:
95: switch (choice)
96: {
97: case 0: fQuit = true;
98: break;
99: case 1: sp = new Circle(5);
100: break;
101: case 2: sp = new Rectangle(4,6);
102: break;
103: case 3: sp = new Square(5);
104: break;
105: default: cout << "Please enter a number between 0 and 3" << endl;
106: continue;
107: break;
108: }
109: if(! fQuit)
110: sp->Draw;
111: delete sp;
112: cout << "\n";
113: }
114: return 0;
115: }
Результат:
(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 X
(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
(1)Circle (2)Rectangle (3)Square (0)Quit:0
Анализ:
Класс Circle производится от класса Shape, и в нем замещаются три виртуальных метода. Обратите внимание, что в данном случае нет необходимости использовать ключевое слово virtual, поскольку виртуальность функций наследуется в производном классе. Тем не менее для напоминания о виртуальности используемых функций не лишним будет явно указать это.
Класс Square производится от класса Rectangle и наследует от него все методы, причем метод GetPerim замещается в новом классе.
Все методы должны функционировать нормально в производных классах, но не в базовом классе Shape, поскольку невозможно создать экземпляр формы как таковой. Программа должна быть защищена от попытки пользователя создать объект этого класса. Класс Shape существует только для того, чтобы поддерживать интерфейс, общий для всех производных классов, поэтому об этом типе данных говорят как об абстрактном, или ADT (Abstract Data Туре).
Абстрактный класс данных представляет общую концепцию, такую как форма, а не отдельные объекты, такие как окружность или квадрат. В C++ ADT по отношению к другим классам всегда выступает как базовый, для которого невозможно создать функциональный объект абстрактного класса.
Чистые виртуальные функции
C++ поддерживает создание абстрактных типов данных с чистыми виртуальными функциями. Чистыми виртуальными функциями называются такие, которые инициализируются нулевым значением, например:
virtual void Draw = 0;
Класс, содержащий чистые виртуальные функции, является ADT. Невозможно создать объект для класса, который является ADT. Попытка создания объекта для такого класса вызовет сообщение об ошибке во время компиляции. Помещение в класс чистой виртуальной функции будет означать следующее:
• невозможность создания объекта этого класса;
• необходимость замещения чистой виртуальной функции в производном классе.
Любой класс, произведенный от ADT, унаследует от него чистую виртуальную функцию, которую необходимо будет заместить, чтобы получить возможность создавать объекты этого класса. Так, если класс Rectangle наследуется от класса Shape, который содержит три чистые виртуальные функции, то в классе Rectangle должны быть замещены все эти три функции, иначе он тоже будет ADT. В листинге 13.8 изменено объявление классa Shape таким образом, чтобы он стал абстрактным типом данных. Остальная часть листинга 13.7 не изменилась, поэтому не приводится. Просто замените объявление класса в строках 7—16 листинга 13.7 листингом 13.8 и запустите программу.
Листинг 13.8. Абстрактные типы данных
1: класс Shape
2: {
3: public:
4: Shape{ }
5: ~Shape{ }.
6: virtual long GetArea = 0; // ошибка
7: virtual long GetPerim= 0;
8: virtual void Draw = 0;
9: private:
10: };
Результат:
(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 x
(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
(1)Circle (2)Rectangle (3)Square (0)Quit: 0
Анализ: Как видите, выполнение программы не изменилось. Просто теперь в программе невозможно создать объект класса Shape.
Абстрактные типы данных
Чтобы объявить класс как абстрактный тип данных.достаточно добавить в него одну или несколько чистых виртуальных функций. Для этогопосле объявления функции необходимо добавить - 0, например:
сlass Shape
{
virtual void Draw = 0; // чистая виртуальная функция
}
Выполнение чистых виртуальных функций
Обычно чистые виртуальные функции объявляются в абстрактном базовом классе и не выполняются. Поскольку невозможно создать объект абстрактного базового класса, как правило, нет необходимости и ff выполнении чистой виртуальной функции. Класс ADT существует только как объявление интерфейса объектов, создаваемых в производных классах.