полиморфизм — Почему я должен повторно объявлять переопределенные функции в производных классах в C ++?

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

class Iinterface
{
virtual void abstractFunction()=0;
};

class Derived : public Iinterface
{
void abstractFunction(); // Do I need this line?
};

Derived::abstractFunction()
{
// implementation here
}

Если я не добавлю соответствующую строку, я получу ошибку компиляции, которая говорит abstractFunction не заявлено в Derived, Я использую VS 2008.
Я не уверен, зачем мне нужна именно эта линия (не путайте это с определением функции, которое предоставляется вне объявления класса), до тех пор, пока я наследую от Iinterface это должно быть очевидно, у меня есть abstractFunction объявлен. Это проблема Visual Studio или это обеспечивается стандартами C ++?

14

Решение

Если бы объявление чисто виртуальных базовых функций подразумевалось во всех производных классах, вы никогда не могли бы иметь производный класс, который остается абстрактным относительно чисто виртуальной базовой функции. Вместо этого все производные классы будут вызывать ошибки компоновщика. Это было бы крайне нелогичным и запутанным, и это сделало бы язык менее выразительным.

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

8

Другие решения

  1. да: Если вы хотите создать объект class Derived
  2. нет: Если вы хотите сохранить class Derived также Аннотация
  3. нет: Если есть промежуточный класс, который уже переопределил функцию
    например между Iinterface а также Derived Eсть class Intermediate который переопределил abstractFunction(); так что теперь это необязательно для class Derived переопределить то же самое

редактировать: С измененным названием вопроса,

Почему я должен повторно объявить переопределенные функции в производных классах в
C ++?

Это потому, что грамматика компилятора C ++ требует, чтобы каждая функция-член class (или же namespace или файл) должен быть объявлен внутри class (или же namespace или файл) тело. Будь это virtual или нормальная функция.
Есть нет хорошая причина нарушить эту последовательность только для virtual функции.

2

Функция, которая заканчивается =0 называется deleted function, это полезно, когда вы не хотите, чтобы объекты, которые используют определенные конструкторы (такие как unique_ptr который имеет удаленную копию ctor).

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

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

Для конкретного примера: допустим, у вас есть List.hpp, List.cpp и main.cpp

В List.hpp у вас есть абстрактный класс и обычный класс, который наследуется от абстрактного класса. В основном ты #include "List.hpp" а не List.cpp, верно? Таким образом, у компилятора НЕТ ИДЕИ, что находится в этом файле (пока он не попытается скомпилировать его). Если у вас нет переопределенной удаленной виртуальной функции, то компилятор думает, что вы просто пытаетесь создать экземпляр абстрактного класса, и выдает ошибку.

С другой стороны, если вы компилируете List.cpp, компилятор также выдаст ошибку, на этот раз жалуясь, что функция, которую вы пытаетесь написать, на самом деле не была определена. Так как Base::deletedFunction() отличается от Derived::deletedFunction(),

1

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

0
По вопросам рекламы [email protected]