Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Итог_Пособие C++.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.03 Mб
Скачать

3.8.3 Множественное наследование

Мы уже говорили, что в С++ у класса-потомка может быть несколько родителей. Такая необходимость возникает довольно редко, и поэтому во многих языках, поддерживающих ООП, возможность множественного наследования не предусмотрена. Но в С++ такая возможность есть и реализуется следующим синтаксисом:

сlass имя_класса: тип_наследования имя_предка1, тип_наследования имя_предка2,…., тип_наследования имя_предкаN

{ тело класса-потомка };

Самый распространенный пример, где используется множественное наследование, – это потоковая библиотека ввода/вывода iostream в стандартном C++. Приведём иерархию классов этой библиотеки в немного упрощенном виде (рисунок 3.2)

Рисунок 3.2 Иерархия классов библиотеки iostream

Два основных видимых пользователю класса этой библиотеки – istream (для ввода) и ostream (для вывода). В число их общих атрибутов входят:

  • информация о форматировании (представляется ли целое число в десятичной, восьмеричной или шестнадцатеричной системе счисления, число с плавающей точкой – в нотации с фиксированной точкой или в научной нотации и т.д.);

  • информация о состоянии (находится ли потоковый объект в нормальном или ошибочном состоянии и т.д.);

  • информация о параметрах локализации (отображается ли в начале даты день или месяц и т.д.);

  • буфер, где хранятся данные, которые нужно прочитать или записать.

Эти общие атрибуты вынесены в отдельный класс ios, для которого istream и ostream являются классами-потомками. Пока речь идёт об одиночном наследовании.

А пример реализации множественного наследования – класс iostream. Он предоставляет поддержку для чтения и записи в один и тот же файл; его предками являются классы istream и ostream.

На рисунке легко выделить геометрическую фигуру – ромб, ограниченную классами ios, istream, ostream, iostream. При такой топологии класс iostream унаследует два различных экземпляра базового класса ios (по одному от istream и ostream), что может привести к дублированию и неоднозначности при вызове методов. Чтобы избежать этих проблем, язык C++ предоставляет специальный вид множественного наследования – виртуальное наследование. Синтаксис изменяется незначительно – в нашем случае достаточно добавить слово virtual в определение классов-родителей класса iostream. Исходя из нашей упрощенной схемы классов ввода-вывода, это может выглядеть так:

class istream : public virtual ios {…}

class ostream : public virtual ios {…}

class iostream : public istream, public ostream {…}

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

3.8.4 Конструкторы и деструкторы классов-потомков

В С++ не наследуются конструкторы и деструкторы базовых классов (хотя бы потому, что имя конструктора должно совпадать с именем класса). Тем не менее, мы можем использовать конструкторы и деструкторы родителей в конструкторах и деструкторах к потомков. Синтаксис реализации конструктора в классе-потомке будет выглядеть следующим образом:

Имя_класса::Имя_класса(список параметров)

: Имя_предка1(список параметров предка)

, Имя_предка2(список параметров предка)

, Инициализация_полей_класса

{

Тело конструктора (может отсутствовать)

}

Если конструктор предка не вызывается из конструктора потомка, то будет вызван конструктор предка по умолчанию.

Приведём пример конструкторов для классов coord и point (по умолчанию и с параметрами). Их стоит добавить в код примера 3.1

// конструктор по умолчанию для класса coord

coord () : x(0), y(0) {}

// конструктор с параметрами для класса coord

coord (int _x, int _y) : x(_x), y(_y) {}

// конструктор по умолчанию для класса point

point () : coord(), r(0), b(0), g(0) {}

// конструктор с параметрами для класса point

point (int _x, int _y, int _r, int _b, int _g) :

coord(_x, _y), r(_r), g(_g), b(_b) {}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]