Создание полноценного класса из абстрактного...255
Подкласс абстрактного класса остаётся абстрактным, пока в нём не переопределены все чисто виртуальные функции. Класс Savings не является абстрактным, поскольку переопределяет чисто виртуальную функцию withdrawal( ) совершенно реальной. Объект класса Savings отлично знает, как реализовать функцию withdrawal( ) и куда обращаться при её вызове. То же касается и класса Checking: он не виртуальный, поскольку withdrawal( ) переопределяет чисто виртуальную функцию, определённую ранее в базовом классе.
_________________
255 стр. Глава 22. Разложение классов
Подкласс абстрактного класса, конечно, может оставаться абстрактным. Разберёмся с приведёнными ниже классами.
class Display
{
public :
virtual void initialize( ) = 0 ;
virtual void write( char *pString ) = 0 ;
} ;
class SVGA : public Display
{
/* Сделаем обе функции-члена "реальными" */
virtual void initialize( ) ;
virtual void write( char *pString ) ;
} ;
class HWVGA : public Display
{
/* Переопределим только одну функцию */
virtual void write( char *pString ) ;
} ;
class ThreedVGA : public HWVGA
{
virtual void initialize( ) ;
} ;
void fn( )
{
SVGA mc ;
VGA vga ;
/* Всё остальное */
}
Класс Display, описывающий дисплеи персонального компьютера, содержит две чисто виртуальные функции: initialize( ) и write( ). Вы не можете ввести эти функции в общем виде. Разные типы видеоадаптеров инициализируются и осуществляют вывод по-разному.
Один из подклассов — SVGA — не абстрактный. Это отдельный тип видеоадаптера, и программист точно знает, как его реализовать. Таким образом, класс SVGA переопределяет обе функции — initialize( ) и write( ) — именно так, как необходимо для данного адаптера.
Ещё один подкласс — HWVGA . Программисту известно, как программировать ускоренный VGA-адаптер. Поэтому между общим классом Display и его частным случаем, ThreedVGA, который представляет собой специальный тип карт 3-D, находится ещё один уровень абстракции.
В нашем обсуждении предположим, что запись во все аппаратно ускоренные карты VGA происходит одинаково ( это не соответствует истине, но представим себе, что это так ). Чтобы правильно выразить общее свойство записи, вводится класс HWVGA, реализующий функцию write( ) ( и другие общие для HWVGA свойства ).
_________________
256 стр. Часть 4. Наследование
При этом функция initialize( ) не переопределяется, поскольку для разных типов карт HWVGA она реализуется по-разному.
Несмотря на то что функция write( ) переопределена в классе HWVGA, он всё равно остаётся абстрактным, так как функция initialize( ) всё ещё не переопределена.
Поскольку ThreedVGA наследуется от HWVGA, он должен переопределить только одну функцию, initialize( ), для того чтобы окончательно определить адаптер дисплея. Таким образом, функция fn( ) может свободно реализовать и использовать объект класса ThreedVGA.
«Замещение нормальной функцией последней чисто виртуальной функции делает класс завершённым ( т.е. неабстрактным ). Только неабстрактные классы могут быть реализованы в виде объектов.»
[Помни!]
Больше книг — больше знаний!
Заберите 20% скидку на все книги Литрес с нашим промокодом
ПОЛУЧИТЬ СКИДКУ