Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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


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

Ответ 2

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

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

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();
};

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

Ответ 3

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

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

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

Ссылка:

С++ 03 Стандарт: 10.3 Виртуальные функции [class.virtual]

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

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

gcc faq также документирует его:

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

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

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

Ответ 4

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

Ответ 5

Да, правильно, что класс Derived должен ОБРАТИТЬ функцию Pure Virtual в родительском классе. Родительский класс, имеющий чистую виртуальную функцию, называется абстрактным классом только потому, что его класс Child должен предоставить свой собственный элемент чистой виртуальной функции.

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

Основной целью механизма виртуальных функций является полиморфизм времени выполнения, независимо от того, является ли основная цель Pure Virtual Function (абстрактного класса) обязательным иметь одно и то же имя Функция с собственным телом.