В этом разделе предлагаются вопросы для самоконтроля и укрепления полученных знаний и приводится несколько упражнений, которые помогут закрепить ваши практические навыки. Попытайтесь самостоятельно ответить на вопросы теста и выполнить задания, а потом сверьте полученные результаты с ответами в приложении Г. Не приступайте к изучению материала следующей главы, если для вас остались неясными хотя бы некоторые из предложенных ниже вопросов.
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;
На прошлом занятии вы узнали, как создавать виртуальные функции в производных классах. На этом занятии речь пойдет об основном составляющем ядре полиморфизма — возможности во время выполнения программы связывать специфические объекты производных классов с указателями базового класса. Сегодня вы узнаете:
• Что такое множественное наследование и как его использовать
• Что представляет собой виртуальное наследование
• Что такое абстрактные типы данных
• Что такое чистые виртуальные функции
Проблемы с одиночным наследованием
Давайте продолжим работу над программой о животных и предположим, что в ней теперь используется два класса, произведенных от какого-то общего класса. Один — 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, данный метод не должен ничего выполнять.
Читать дальше