Все ли виртуальные функции должны быть реализованы в производных классах?


Это может показаться простой вопрос, но я не могу найти ответ нигде.

предположим, что у меня есть следующее:

class Abstract {
public:
    virtual void foo() = 0;
    virtual void bar();
}

class Derived : Abstract {
public:
    virtual void foo();
}

нормально ли, что производный класс не реализует функцию bar ()? Что делать, если не все мои производные классы нуждаются в функции bar (), но некоторые из них. Делать все виртуальные функции абстрактного базового класса должны быть реализованы в производных классах, или только те, которые являются чисто виртуальными? Спасибо

5 76

5 ответов:

производные классы делать не реализовать все виртуальные функции. Им нужно только реализовать чисто те.1 что означает Derived класс в вопросе правильный. Это наследует the bar реализация от своего класса-предка, Abstract. (Это предполагает, что Abstract::bar реализуется где-то. Код в вопросе объявляет метод, но не определяет его. Вы можете определить его встроенным как ответ Тренки показывает, или вы можете задать его отдельно.)


1 и даже тогда, только если производный класс будет инстанцировать. Если производный класс не создается непосредственно, а существует только как базовый класс более производных классов, то это те классы, которые отвечают за реализацию всех своих чисто виртуальных методов. "Среднему" классу в иерархии разрешено оставить некоторые чистые виртуальные методы не реализованы, как и базовый класс. Если "средний" класс тут реализовать чистый виртуальный метод, то его потомки унаследуют эту реализацию, так что они не должны повторно реализовать его сами.

только чисто виртуальные методы должны быть реализованы в производных классах, но вам все еще нужно определение (а не просто декларации) других виртуальных методов. Если вы не поставите один, компоновщик может очень хорошо жаловаться.

Итак, просто ставим {} после того, как ваш дополнительный виртуальный метод дает вам пустую реализацию по умолчанию:

class Abstract {
public:
    virtual void foo() = 0; // pure virtual must be overridden
    virtual void bar() {}   // virtual with empty default implementation
};

class Derived : Abstract {
public:
    virtual void foo();
};

более сложная реализация по умолчанию будет отправлена в отдельный исходный файл.

стандарт ISO C++ указывает, что все виртуальные методы класса, которые не являются чисто виртуальными, должны быть определены.

проще говоря правило:
Если производный класс переопределяет виртуальный метод базового класса, он также должен предоставить определение, если нет, то базовый класс должен предоставить определение этого метода.

согласно приведенному выше правилу в вашем примере кода virtual void bar(); требуется определение в базе класс.

ссылки:

стандарт C++03: 10.3 виртуальные функции [класс.виртуальный]

виртуальная функция, объявленная в классе, должна быть определена или объявлена чистой (10.4) в этом классе, или и то и другое; но никакой диагностики не требуется (3.2).

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

The чаво ССЗ doccuments это как ну:

стандарт ISO C++ указывает, что все виртуальные методы класса, которые не являются чисто виртуальными, должны быть определены, но не требуют никакой диагностики для нарушений этого правила [class.virtual]/8. Исходя из этого предположения, GCC будет выдавать только неявно определенные конструкторы, оператор присваивания, деструктор и виртуальную таблицу класса в блоке трансляции, который определяет его первый такой нестрочный метод.

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

решение состоит в том, чтобы убедиться, что все виртуальные методы, которые не являются чистыми определены. Обратите внимание, что деструктор должен быть определен, даже если он объявлен чисто виртуальным [class.dtor]/7.

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

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

для обычных виртуальных функций:- Нет необходимости переопределять их дальше, так как некоторые дочерние классы могут иметь эту функцию, а некоторые-нет.

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