Рейтинговые книги
Читем онлайн Освой самостоятельно С++ за 21 день. - Джесс Либерти

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 78 79 80 81 82 83 84 85 86 ... 170

Массивы могут быть одномерными или многомерными. Независимо от размерности, все массивы базовых типов (например, int) или массивы объектов классов с конструкторами, заданными по умолчанию, могут быть инициализированы при объявлении.

Объекты массивов или все массивы целиком можно сохранять как в стековой области памяти, так и в области динамического обмена. Если удаляется объект из области динамической памяти, не забудьте установить квадратные скобки после ключевого слова delete[].

Имена массивов представляют собой константные указатели на первый элемент массива. Чтобы получить доступ к другим элементам, имена массивов можно использовать в математических операциях, как при работе с обычными указателями.

Если размер коллекции объектов не известен во время компиляции программы, то для поддержания таких коллекций можно использовать связанные списки. Взяв связанный список за основу, можно разработать много других видов массивов и структур, автоматически выполняющих сложные операции.

Строки представляют собой массивы символов. В C++ существуют дополнительные средства манипулирования текстовыми строками, включая возможность ввода в массив строки, взятой в двойные кавычки.

Вопросы и ответы

Что произойдет, если в массив из 24-х членов вписать значение для 25-го элемента?

Значение будет добавлено в ячейку памяти, не принадлежащую массиву, что может вызвать серьезную ошибку в работе программы.

Что представляют собой элементы неинициализированного массива?

Ячейки памяти, отведенные массиву но не инициализированные, могут содержать любую информацию, ранее сохраненную в этих ячейках. Результат обращения в программе к элементу массива, который не был инициализирован, не предсказуем.

Можно ли создавать комбинации массивов?

Да. Массив может содержать указатель на другой, более крупный массив. В случае работы со строками можно использовать некоторые стандартные функции, такие как strcat, чтобы создавать комбинации массивов символов.

Чем связанные списки лучше массивов?

Массивы всегда имеют фиксированный размер, тогда как размер связанного списка может изменяться динамически во время выполнения программы.

Всегда ли нужно в классе строк использовать указатель char * для сохранения содержимого строки?

Нет. Можно использовать любую область памяти, которая больше подходит для решения конкретных задач.

Коллоквиум

В этом разделе предлагаются вопросы для самоконтроля и укрепления полученных знаний и приводится несколько упражнений, которые помогут закрепить ваши практические навыки. Попытайтесь самостоятельно ответить на вопросы теста и выполнить задания, а потом сверьте полученные результаты с ответами в приложении Г. Не приступайте к изучению материала следующей главы, если для вас остались неясными хотя бы некоторые из предложенных ниже вопросов.

Контрольные вопросы

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 таким образом, что при вызове его объект заявляет, что умеет летать.

1 ... 78 79 80 81 82 83 84 85 86 ... 170
На этой странице вы можете бесплатно читать книгу Освой самостоятельно С++ за 21 день. - Джесс Либерти бесплатно.

Оставить комментарий