Язык обладает синтаксической конструкцией, обозначающей, что некоторая виртуальная функция предоставляет интерфейс, который должен быть замещен в производных подтипах, но вызываться непосредственно не может. Это чисто виртуальные функции. Объявляются они следующим образом:
class Query {
public:
// объявляется чисто виртуальная функция
virtual ostream& print( ostream&=cout ) const = 0;
// ...
};
Заметьте, что за объявлением функции следует присваивание нуля.
Класс, содержащий (или наследующий) одну или несколько таких функций, распознается компилятором как абстрактный базовый класс. Попытка создать независимый объект абстрактного класса приводит к ошибке компиляции. (Ошибкой является также вызов чисто виртуальной функции с помощью механизма виртуализации.) Например:
// В классе Query объявлены одна или несколько виртуальных функций,
// поэтому программист не может создавать независимые объекты
// класса Query
// правильно: подобъект Query в составе NameQuery
Query *pq = new NameQuery( "Nostromo" );
// ошибка: оператор new создает объект класса Query
Query *pq2 = new Query;
Абстрактный базовый класс может существовать только как подобъект в составе объекта некоторого производного от него класса. Это именно та семантика, которая нужна нам для базового Query.