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

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

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

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

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

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

78 голосов | спросил mikestaub 19 Jpm1000000pmThu, 19 Jan 2012 22:51:12 +040012 2012, 22:51:12

5 ответов


0

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


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

ответил Rob Kennedy 19 Jpm1000000pmThu, 19 Jan 2012 22:52:19 +040012 2012, 22:52:19
0

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

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

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

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

ответил trenki 19 Jpm1000000pmThu, 19 Jan 2012 23:00:24 +040012 2012, 23:00:24
0

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

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

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

Ссылка:

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

  

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

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

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

  

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

     

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

     

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

ответил Alok Save 19 Jpm1000000pmThu, 19 Jan 2012 23:10:47 +040012 2012, 23:10:47
0

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

ответил Jason 19 Jpm1000000pmThu, 19 Jan 2012 22:52:20 +040012 2012, 22:52:20
0

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

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

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

ответил CodeCodeCode 19 Jpm1000000pmThu, 19 Jan 2012 23:36:37 +040012 2012, 23:36:37

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132