27: }
28:
29: class Mammal : public Animal
30: {
31: public:
32: Mammal(int age):Animal(age)
33: { cout << "Mammal constructor...\n";}
34: virtual ~Mammal() { cout << "Mammal destructor...\n";}
35: virtual void Reproduce() const
36: { cout << "Mammal reproduction depicted...\n"; }
37: };
38:
39: class Fish : public Animal
40: {
41: public:
42: Fish(int age):Animal(age)
43: { cout << "Fish constructor...\n";}
44: virtual ~Fish() { cout << "Fish destructor...\n"; }
45: virtual void Sleep() const { cout << "fish snoring...\n"; }
46: virtual void Eat() const { cout << "fish feeding...\n"; }
47: virtual void Reproduce() const
48: { cout << "fish laying eggs...\n"; }
49: virtual void Move() const
50: { cout << "fish swimming...\n"; }
51: virtual void Speak() const { }
52: };
53:
54: class Horse : public Mammal
55: {
56: public:
57: Horse(int age, COLOR color ):
58: Mamrnal(age), itsColor(color)
59: { cout << "Horse constructor...\n"; }
60: virtual ~Horse() { cout << "Horse destructor...\n"; }
61: virtual void Speak()const { cout << "Whinny!... \n"; }
62: virtual COLOR GetItsColor() const { return itsColor; }
63: virtual void Sleep() const
64: { cout << "Horse snoring.,.\n"; }
65: virtual void Eat() const { cout << "Horse feeding...\n"; }
66: virtual void Move() const { cout << "Horse running...\n";} 67:
68: protected:
69: COLOR itsColor;
70: };
71:
72: class Dog : public Mammal
73: {
74: public:
75: Dog(int age, COLOR color ):
76: Mammal(age), itsColor(color)
77: { cout << "Dog constructor...\n"; }
78: virtual ~Dog() { cout << "Dog destructor...\n"; }
79: virtual void Speak()const { cout << "Woof!... \n"; }
80: virtual void 51eep() const { cout << "Dog snoring...\n"; }
81: virtual void Eat() const { cout << "0og eating...\n"; }
82: virtual void Move() const { cout << "Dog running...\n"; }
83: virtual void Reproduce() const
84: { cout << "Dogs reproducing...\n"; }
85:
86: protected:
87: COLOR itsColor;
88: };
89:
90: int main()
91: {
92: Animal *pAnimal=0;
93: int choice;
94: bool fQuit = false;
95:
96: while (1)
97: {
98: cout << "(1)Dog (2)Horse (3)Fish(0)Quit: ";
99: cin >> choice; 100:
101: switch (choice)
102: {
103: case 1: pAnimal = new Dog(5,Brown);
104: break;
105: case 2: pAnimal = new Horse(4,Black);
106: break;
107: case 3: pAnimal = new
108: break;
109: default: fQuit = true
110: break;
111: }
112: if (fQuit)
113: break;
114:
115: pAnimal->Speak();
116: pAnimal->Eat();
117: pAnimal->Reproduce();
118: pAnimal->Move();
119: pAnimal->Sleep();
120: delete pAnimal;
121: cout << "\n";
122: }
123: return 0;
124: }
Результат:
(1)Dog (2)Horse (3)Bird (0)Quit: 1
Animal constructor. . .
Mammal constructor...
Dog constructor...
Woof!...
Dog eating. . .
Dog reproducing....
Dog running...
Dog snoring...
Dog destructor...
Mammal destructor...
Animal destructor...
(1)Dog (2)Horse (3)Bird (0)Quit: 0
Анализ:В строках 7—21 объявляется абстрактный тип данных Animal. Единственный метод этого класса, не являющийся чистой виртуальной функцией, это общий для объектов всех производных классов метод itsAge. Остальные пять методов — Sleep(), Eat(), Reproduce(), Move() и Speak() — объявлены как чистые виртуальные функции.
Класс Mammal производится от Animal в строках 29—37 и не содержит никаких данных. В нем замещается функция Reproduce(), чтобы задать способ размножения, общий для всех млекопитающих. Класс Fish производится непосредственно от класса Animal, поэтому функция Reproduce() в нем замещается иначе, чем в классе Mammal (и это соответствует реальности).
Во всех других классах, производимых от класса Mammal, теперь нет необходимости замещать общий для всех метод Reproduce(), хотя при желании это можно сделать для определенного класса, как, например, в нашей программе это было сделано в строке 83 для класса Dog. Все остальные чистые виртуальные функции были замещены в классах Fish, Horse и Dog, поэтому для каждого из них можно создавать соответствующие объекты.
В теле программы используется указатель класса Animal, с помощью которого делаются ссылки на все объекты производных классов. В зависимости от того, с каким объектом связан указатель в текущий момент, вызываются соответствующие виртуальные функции.
При попытке создать объекты для классов абстрактных типов данных Animal или Mammal компилятор покажет сообщение об ошибке.
Когда следует использовать абстрактные типы данных
В одних примерах программ, рассмотренных нами ранее, класс Animal являлся абстрактным типом данных, в других — нет. В каких же случаях нужно объявлять класс как абстрактный тип данных?
Нет никаких правил, которые требовали бы объявления класса как абстрактного. Программист принимает решение о создании абстрактного типа данных, основываясь на том, какую роль играет этот класс в программе. Так, если вы хотите смоделировать виртуальную ферму или зоопарк, то имеет смысл класс Animal объявить как абстрактный и для создания объектов производить от него другие классы, такие как Dog.
Если же вы хотите смоделировать виртуальную псарню, то теперь класс Dog будет абстрактным, от которого можно производить подклассы, представляющие разные породы собак. Количество уровней абстрактных классов следует выбирать в зависимости от того, насколько детально вы хотите смоделировать реальный объект или явление.
Читать дальше