Освой самостоятельно С++ за 21 день.
Шрифт:
Контрольные вопросы
1. Как обратиться к первому и последнему элементам массива SomeArray[25]?
2. Как объявить многомерный массив?
3. Выполните инициализацию элементов многомерного массива, созданного при ответе на вопрос 2.
4. Сколько элементов содержит массив SomeArray[10][5][20]?
5. Каково максимальное число элементов, которые можно добавить в связанный список?
6. Можно ли в связанном списке использовать индексы?
7. Каким является последний символ в строке "Сергей — хороший парень"?
Упражнения
1. Объявите
2. Запишите программный код, инициализирующий значением 0 все элементы созданного перед этим массива.
3. Объявите класс узла Node, поддерживающего целые числа.
4. Жучки: что неправильно в следующей программе?
unsigned short SomeArray[5][4];
for (int i = 0; i<4; i++)
for (int j = 0; j<5; ]++)
SomeArray[i][j] = i+j;
5. Жучки: что неправильно в следующей программе?
unsigned short SomeArray[5][4];
for (int i = 0; i<=5; i++)
for (int j = 0; j<=4; j++)
SomeArray[i][j] = 0;
День 13-й. Полиморфизм
На прошлом занятии вы узнали, как создавать виртуальные функции в производных классах. На этом занятии речь пойдет об основном составляющем ядре полиморфизма — возможности во время выполнения программы связывать специфические объекты производных классов с указателями базового класса. Сегодня вы узнаете:
• Что такое множественное наследование и как его использовать
• Что представляет собой виртуальное наследование
• Что такое абстрактные типы данных
• Что такое чистые виртуальные функции
Проблемы с одиночным наследованием
Давайте продолжим работу над программой о животных и предположим, что в ней теперь используется два класса, произведенных от какого-то общего класса. Один — Bird, посвященный птицам, а другой — Mammals, посвященный млекопитающим. Класс Bird содержит функцию-член Fly, задающую возможность полета. Класс Mammals разбит на ряд подклассов, включая класс лошадей — Horse. Класс содержит две функции- члена — Whinny и Gallop, объявляющих ржание и бег галопом соответственно.
Но внезапно у вас возникает желание создать новый весьма интересный мифический объект — крылатого Пегаса (Pegasus), который был бы чем-то вроде гибрида между Horse и Bird. Сразу предупредим, что, используя только одиночное наследование, вам сложно будет справиться с этой задачей.
Если объявить объект Pegasus как член класса Bird, то для него станут недоступными функции Whinny и Gallop. Если Pegasus объявить как объект класса Horse, то ему станет недоступной функция Fly.
Первое решение может состоять в том, чтобы скопировать метод Fly в класс Horse, после чего в этом классе создать объект Pegasus. При этом оба класса (Bird и Horse) будут содержать один и тот же метод Fly, и при изменении метода в одном классе нужно будет не забыть внести соответствующие изменения в другом классе. Хорошо, если таких классов будет только два. Если вам придется вносить изменения в программу через некоторое время после ее создания, будет сложно вспомнить, в каких еще классах представлен этот метод.
Когда вы захотите создать списки объектов классов Bird и Horse, перед вами
возникнет еще одна проблема. Хотелось бы, чтобы объект Pegasus был представлен в обоих списках, но в данном случае это невозможно.Для решения возникшей проблемы можно использовать несколько подходов. Haпример, можно переименовать слишком "лошадиный" метод Gallop в более обтекаемый Move, после чего заместить этот метод в объекте Pegasus таким образом, чтобы он выполнял функцию метода Fly. В других объектах класса Horse метод Move будет выполняться так же, как раньше выполнялся метод Gallop. Для объекта Pegasus можно даже определить, что короткие дистанции он должен преодолевать методом Gallop, а длинные — методом Fly:
Pegasus::Move(long distance)
{
if (distance > veryFar)
fly(distance);
else
gallop(distance);
}
Но и этот подход имеет ряд ограничений, поскольку объект уже не сможет летать на короткие дистанции и бегать на длинные. Может быть, все же просто перенести метод Fly в класс Horse, как показано в листинге 13.1? Проблема состоит в том, что лошади, в большинстве своем, летать не умеют, поэтому во всех объектах этого класса, за исключением объекта Pegasus, данный метод не должен ничего выполнять.
Листинг 13.1. Умеют ли лошади летать...
1: // Листинг 13.1. Умеют ли лошади летать...
2: // Фильтрация метода Fly в классе Horse
3:
4: #include <iostream.h>
5:
6: class Horse
7: {
8: public:
9: void Gallop{ cout << "Galloping...\n"; }
10: virtual void Fly { cout << "Horses can't fly.\n"; }
11: private:
12: int itsAge;
13: };
14:
15: class Pegasus : public Horse
16: {
17: public:
18: virtual void Fly { cout << "I can fly! I can fly! I can fly!\n"; }
19: };
20:
21: const int NumberHorses = 5;
22: int main
23: {
24: Horse* Ranch[NumberHorses];
25: Horse* pHorse;
26: int choice,i;
27: for (i=0; i<NumberHorses; i++)
28: {
29: cout << "(1)Horse (2)Pegasus: ";
30: cin >> choice;
31: if (choice == 2)
32: pHorse = new Pegasus;
33: else
34: pHorse = new Horse;
35: Ranch[i] = pHorse;
36: }
37: cout << "\n";
38: for (i=0; i<NumberHorses; i++)
39: {
40: Ranch[i]->Fly;
41: delete Ranch[i];
42: }
43: return 0;
44: }
Результат:
(1)Horse (2)Pegasus; 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 1
Horses can't fly.
I can fly! I can fly! I can fly!
Horses can't fly.
I can fly! I can fly! I can fly!
Horses can't fly.
Анализ: Безусловно, эта программа будет работать ценой добавления в класс Horse редко используемого метода Fly. Это произошло в строке 10. Для объектов данного класса этот метод констатирует факт, что лошади летать не умеют. И только для объекта Pegasus метод замещается в строке 18 таким образом, что при вызове его объект заявляет, что умеет летать.