Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по С++ глава 4.doc
Скачиваний:
4
Добавлен:
05.11.2018
Размер:
131.07 Кб
Скачать

4.5.2. Применение виртуальных функций для модификации базовых классов

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

class CMessageBox

{

protected:

char *Message;

virtual void DrawBackground (int L, int T, int R, int B);

// закрашивает фон окна сообщения в белый цвет

public:

CMessageBox()

{

Message = new char (‘\0'};

}

~CMessageBox()

{

delete [] Message;

}

void Display()

{

DrawBackground (0, 0, 35, 25); // код для вывода строки сообщения ...

}

void Set (char *Msg);

};

Открытая функция-член Set позволяет передать строку сообщения, a Display выводит это сообщение на экран. Отметим: функция Display очищает фон, вызывая другую функцию-член DrawBackground и передавая ей размеры окна сообщения. Эта функция закрашивает фон, используя непрозрачный белый цвет. Функция DrawBackground предназначена для использования внутри класса. Она не предназначена для вызова извне класса и, следовательно, объявлена как защищенный член класса.

Функция DrawBackground также объявлена виртуальной. Соответственно, при порождении от класса CMessageBox нового класса, содержащего собственную версию DrawBackGround, новая функция перекроет старую, даже если будет вызываться из функции-члена класса CMessageBox. Например, от класса CMessageBox можно породить следующий класс.

class CMyMessageBox : public CMessageBox

{

protected:

virtual void DrawBackground (int L, int T, int R, int B)

{

// закрашивает фон окна сообщения СИНИМ цветом ...

}

};

Обратите внимание: новая версия функции DrawBackground создает синий фон, а не белый. Следовательно, в приведенном ниже фрагменте будет создано окно сообщения с синим фоном.

CMyMessageBox MyMessageBox;

MyMessageBox.Set ("hello");

MyMessageBox.Display ();

Делая функцию DrawBackground виртуальной, мы получаем возможность настраивать класс CMessageBox (а именно, цвет или узор, которым заполняется фон окна сообщения) без модификации исходного текста данного класса (при этом даже не нужно просматривать исходный программный код). Многие классы, определенные в библиотеке MFC, предусматривают использование виртуальных функций, которые можно переопределять в производных классах, что позволяет легко модифицировать MFC-классы.

Механизм переопределения

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

Вспомним: ссылка на член класса из функции-члена неявно связана с применением указателя this. Таким образом, функцию Display класса CMessageBox можно записать следующим способом.

class CMessageBox

{

// другие определения ...

public:

void Display()

{

this->DrawBackground (0, О, 35, 25);

// ...

}

// другие определения ...

};

Если бы функция DrawBackground не являлась виртуальной, то ее вызов из функции Display инициализировал бы вызов версии DrawBackground класса CMessageBox (так как в пределах этого класса указатель this является указателем на объект класса CMessageBox). Однако если функция DrawBackground является виртуальной, ее вызов инициализирует вызов версии DrawBackground класса текущего объекта. Таким образом, если функция Display вызвана для объекта класса CMyMessageBox, то будет вызвана и DrawBackground, определенная внутри данного класса.

CMyMessageBox MyMessagBox;

// ...

MyMessageBox.Display ();