#include <iostream>
using namespace std;
class Duck {
public:
virtual void quack() = 0;
};
class BigDuck : public Duck {
public:
// void quack(); (uncommenting will make it compile)
};
void BigDuck::quack(){ cout << "BigDuckDuck::Quack\n"; }
int main() {
BigDuck b;
Duck *d = &b;
d->quack();
}
Код выше не компилирует. Однако, когда я объявляю виртуальную функцию в подклассе, затем это компилирует прекрасный.
Если компилятор уже имеет подпись функции, которую подкласс переопределит, то, почему redeclaration требуется?
Какое-либо понимание?
Передекларирование необходимо, потому что:
Если вы измените:
virtual void quack() = 0;
на
virtual void quack();
, он будет компилироваться без реализации quack () в HugeDuck.
= 0; в конце объявления функции, по сути, говорится, что все BigDucks будут крякать, но это должно быть реализовано каждой производной уткой. Удалив = 0; будет вызываться шарлатан BigDuck, если вы не реализуете шарлатан в HugeDuck.
РЕДАКТИРОВАТЬ: Чтобы уточнить = 0; говорит, что производный класс будет иметь определение функции. В вашем примере ожидается, что HugeDuck определит quack (), но, поскольку вы это закомментировали, это не так.
В качестве примечания, поскольку все утки могут крякать, возможно, ваш исходный класс Duck, который мы не видим, должен вместо этого реализовать quack ()?
Поскольку C ++ отделяет «объявление» от «полиморфизма»: любая функция нуждается в объявлении для компилятора, независимо от виртуальный он или нет.
Ваш пример не идет достаточно далеко, у него есть проблема «абстрактного класса»: BigDuck не может быть создан, потому что в его интерфейсе нет реализации шарлатана.
Обобщая проблему, мы можем объявить базовую функцию , а не чистой виртуальной:
class Duck { public: virtual void quack(){} };
class BigDuck : public Duck {};
void BigDuck::quack(){ cout << "QUACK!"; }//overrides, but doesn't declare
Здесь компилятор будет жаловаться, что у него есть символ BigDuck :: quack
, который не был Не заявлено. Это не имеет ничего общего с абстрактными классами или чем-то еще.
(Примечание: gcc говорит:
ошибка: в классе BigDuck не объявлена функция-член void BigDuck :: q ()
)
Определение Quack()
в вашем базовом классе является "абстрактным" - оно не имеет реализации. Это говорит компилятору, что ваш производный класс должен реализовать его. Неспособность сделать это является ошибкой компиляции.
BigDuck может быть другим абстрактным классом, и вы, возможно, не захотите реализовать шарлатанство, пока не дойдете до базового класса ReallyBigDuck.
Пока вы не предоставите реализацию, все классы, наследующие от класса, содержащего Чистую виртуальную функцию
, являются абстрактными - их нельзя создать . Чтобы предоставить такую реализацию, вы должны объявить функцию в классе.
Объявление методов в каждом классе сообщит компилятору, что класс предоставляет различные реализации для метода.
Кроме того,
если вы хотите создать объекты BigDuck
в стеке, то как компилятор должен знать сигнатуру quack ()
.
BigDuck aDuck;
aDuck.quack();