Шаг 26.
Множественное наследование

    На этом шаге мы приведем общие сведения о множественном наследовании.

    Начнем с определений.

    Класс называют непосредственным (прямым) базовым классом (прямой базой), если он входит в список базовых при определении класса. В то же время для производного класса могут существовать косвенные или непрямые предшественники, которые служат базовыми для классов, входящих в список базовых. Если некоторый класс A является базовым для B и B есть база для C, то класс B является непосредственным базовым классом для C, а класс А - непрямой базовый класс для C (рисунок 1).


Рис.1. Прямое и косвенное наследование классов

   

    Обращение к компоненту XA, входящему в A и унаследованному последовательно классами B и C, можно обозначить в классе C либо как А::XA, либо как В::XA. Обе конструкции обеспечивают обращение к элементу XA класса А.

    Иерархию производных классов удобно представлять с помощью направленного ациклического графа (НАГ), где стрелкой изображают отношение "производный от". Производные классы принято изображать ниже базовых. Именно в таком порядке их объявления рассматривает компилятор и их тексты размещаются в листинге программы. Класс может иметь несколько непосредственных базовых классов, т.е. может быть порожден из любого числа базовых классов, например:

class X1 { ... }; 
class X2 { ... } ; 
class ХЗ { ... } ; 
class Y1: public X1, public X2, public X3 { ... };

    Наличие нескольких прямых базовых классов называют множественным наследованием. В качестве примера рассмотрим производный класс "звезда, вписанная в квадрат". Базовыми классами будут: звезда (star) и квадрат (square). Класс "звезда" был описан раннее (он базируется на класе point), а класс square определим следующим образом:

// SQUARE.CPP - класс "квадрат".
#ifndef SQUARE
#define SQUARE 1
#include <conio.h>   //Для функции gotoxy();
class square
{
   int xq,yq,       //Координаты центра квадрата.
          lq;       //Длина стороны квадрата.
   //Вспомогательная функция рисования:
   void rissquare(void);
 public:
   // Конструктор класса SQUARE:
   square (int xi, int yi, int li)
      {  xq = xi; yq = yi; lq = li;  }
   ~square()     // Деструктор класса SQUARE.
     { hide();    // Убрать с экрана изображение квадрата.
	}
  void hide();    // Убрать с экрана изображение квадрата.

void show() //Изобразить квадрат на экране дисплея.
{ rissquare();
}

}; //Конец определения класса.

void square::rissquare(void)
{
  int d=lq/2;
  for (int i=-d; i<=d; i++)
    {
      gotoxy(xq+i,yq+d); cout << "=";
      gotoxy(xq+i,yq-d); cout << "=";
    }
  for (int j=-d; j<=d; j++)
    {
      gotoxy(xq-d,yq+j); cout << "=";
      gotoxy(xq+d,yq+j); cout << "=";
    }
}

void square::hide()      // Убрать с экрана изображение квадрата.
{
  // Стереть изображение с экрана:
  int d=lq/2;
  for (int i=-d; i<=d; i++)
    {
      gotoxy(xq+i,yq+d); cout << " ";
      gotoxy(xq+i,yq-d); cout << " ";
    }
  for (int j=-d; j<=d; j++)
    {
     gotoxy(xq-d,yq+j); cout << " ";
     gotoxy(xq+d,yq+j); cout << " ";
    }
}
#endif
Текст этого класса можно взять здесь.

    В следующей программе на основе классов star и square создан производный класс "звезда в квадрате" с именем starsqrt:

#include "square.cpp"
#include "star.cpp"
class starsqrt: public star, public square
{
  public:
   starsqrt (int xi, int yi, int ri):
		star(xi,yi,ri),
		square (xi,yi,2*ri) {}
  void show()
  { star::show();
	 square::show(); }
  void hide ()
  { star::hide();
	 square::hide(); }
};

void main()
{
  starsqrt A(5,7,4);
  starsqrt B(18,12,6);
  A.show();  getch();
  B.show();  getch();
  A.hide();  getch();
  B.hide();  getch();
}
Текст этой программы и остальные классы можно взять здесь.

    Определения базовых классов должны предшествовать их использованию в качестве базовых. Поэтому тексты из файлов square.срр и star.cpp включены в начало программы, после чего описывается класс starsqrt. В производном классе starsqrt телом конструктора служит пустой оператор. Выполнение конструктора starsqrt() сводится к последовательному вызову конструкторов базовых классов. При этом за счет соответствующего выбора параметров центры обеих фигур (квадрата и звезды) совпадают. Кроме того, длина стороны квадрата выбирается равной удвоенной длине луча звезды (параметр 2*ri), и тем самым звезда оказывается вписанной в квадрат.

    В основной программе формируются два объекта A, B класса starsqrt. Они последовательно выводятся на экран дисплея и в обратном порядке убираются с экрана.

    На следующем шаге мы продолжим знакомство с множественным наследованием.




Предыдущий шаг Содержание Следующий шаг