Чистая реализация виртуальной функции

Я читаю " Эффективный C++" Скотта Мейерса, и я нахожусь в разделе о наследовании. Он сказал, что

Чистые виртуальные функции определяют только наследование интерфейса.

Простые (нечистые) виртуальные функции определяют наследование интерфейса плюс наследование реализации по умолчанию.

Теперь рассмотрим следующие два класса:

struct A {
    virtual void foo() = 0;
};

void A::foo(){ std::cout << "Default foo" << std::endl; }

struct B : A{
    virtual void foo(){ A::foo(); std::cout << "Derived foo" << std::endl; }
};

Мы все еще можем предоставить реализацию по умолчанию для чисто виртуальных функций, как я сделал в примере, и вызвать ее через qualified-function-call-expression, Мы можем сделать почти то же самое для нечистых виртуальных функций

struct A {
    virtual void foo(); //No longer pure virtual
};

void A::foo(){ std::cout << "Default foo" << std::endl; }

struct B : A{
    virtual void foo(){ A::foo(); std::cout << "Derived foo" << std::endl; }
};

Если я не определяю нечистую виртуальную функцию следующим образом:

struct A {
    virtual void foo();
};



struct B : A{
    virtual void foo(){ std::cout << "Derived foo" << std::endl; }
};

это будет прекрасно работать.

DEMO

Итак, единственная цель чисто виртуальных функций - сделать класс абстрактным (неинстанцируемым)?

1 ответ

Решение

Чистая виртуальная функция не только делает базовый класс неинстанцируемым, но и заставляет все производные классы реализовывать соответствующую виртуальную функцию. Если вы не сделаете базовую функцию чисто виртуальной, то производные классы могут отказаться от ее реализации. Определение чисто виртуальной функции - это нормально, если вы используете ее из производного экземпляра, и она обеспечивает реализацию, которую можно использовать по умолчанию, как указывает Скотт Мейерс.

Обратите внимание, что ваша демонстрация не работает так, как вы думаете. Если вы делаете то, что обычно считается обычным при использовании полиморфизма,

A* p = new B; // or, std::unique_ptr<A> p = make_unique<B>();
p->foo();

тогда вы получите неприятную ошибку компоновщика:

Неопределенные символы для архитектуры x86_64:

"typeinfo для A", ссылка на которую: typeinfo для B в ccoVYpAI.o

Другие вопросы по тегам