Ну хорошо, чисто виртуальная функция — это функция-член без тела функции ( которого нет, например, потому, что никто не знает, как реализовать это самое тело ).
Бессмысленно спрашивать о том, каким должно быть тело функции withdrawal( ) в классе Account . Хотя, конечно, сама концепция снятия денег со счёта имеет смысл. Программист на С++ может написать функцию withdrawal( ) , которая будет отражать концепцию снятия денег со счёта, но при этом данная функция не будет иметь тела, поскольку мы не знаем, как её реализовать. Такая функция называется чисто виртуальной [ 17 ]( не спрашивайте меня, откуда взялось это название ).
Синтаксис объявления чисто виртуальной функции показан в приведённом ниже классе Account .
/* Account — это абстрактный класс */
class Account
{
protected :
Account( Account & с ) ;
public :
Account( unsigned accNo , float initialBalance = 0.0F ) ;
/* Функции доступа */
unsigned int accountNo( ) ;
float acntBalance( ) ;
static int noAccounts( ) ;
static Account *first( ) ;
Account *next( ) ;
/* Функции транзакций */
void deposit( ) ;
/* Приведённая ниже функция является чисто виртуальной */
virtual void withdrawal( float amount ) = 0 ;
protected :
/* Если хранить счета в связанном списке, не будет ограничения на их количество */
static Account *pFirst ;
Account *pNext ;
static int count ; /* Количество счетов */
unsigned accountNumber ;
float balance ;
} ;
______________
17Вообще говоря, чисто виртуальная функция может иметь тело, но обсуждение этого вопроса выходит за рамки данной книги. — Прим. ред.
_________________
254 стр. Часть 4. Наследование
Наличие после объявления функции withdrawal( ) символов = 0 показывает, что программист не намеревается в данный момент определять эту функцию. Такое объявление просто занимает место для тела функции, которое позже будет реализовано в подклассах. От подклассов класса Account ожидается, что они переопределят эту функцию более конкретно.

«Я считаю это объяснение глупым, и мне оно нравится не более чем вам, так что просто выучите и живите с ним. Для этого объяснения есть причина, если не оправдание. Каждая виртуальная функция должна иметь свою ячейку в специальной таблице, в которой содержится адрес функции. Так вот: ячейка для чисто виртуальной функции содержит нуль.»
[ Технические подробности ]
Абстрактный класс не может быть реализован; другими словами, вы не можете создать объект абстрактного класса. Например, приведённое ниже объявление некорректно.
void fn( )
{
Account acnt( 1234, 100.00 ) ; /* Это некорректно */
acnt.withdrawal( 50 ) ; /* Куда, по-вашему, должен обращаться этот вызов? */
}
Если бы такое объявление было разрешено, конечный объект оказался бы незавершённым, поскольку был бы лишён некоторых возможностей. Например, что бы выполнял приведённый в этом же объявлении вызов? Помните, функции Account::withdrawal( ) не существует.
Абстрактные классы служат базой для других классов. Account содержит универсальные свойства для всех банковских счетов. Вы можете создать другие типы банковских счетов, наследуя класс Account , но сам этот класс не может быть реализован.
Создание полноценного класса из абстрактного...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 ) ;
Читать дальше