OpenID может быть лучше не бывает, но я был приведен, никакая причина для доверия "им" с моими идентификационными данными - кроме Jeff Atwood/Joel Spolsky не заставила меня сделать это, чтобы здесь жаловаться на это;-)
class Visitor;
class England : public Land {
public:
void accept(const Visitor *v); // Only declaration
};
// Define Visitor
class Visitor {
//...
};
// Now implementation
void England::accept(const Visitor *v) {
v->visit(this);
}
Алекси уже дал часть ответа.
Однако, если вы не собираетесь реализовывать accept для Land, вам потребуется:
class Land {
public:
virtual void accept(const Visitor *v)= NULL;
};
Ответ Алексея Малистова решает вашу проблему. Это просто также обнажает следующую проблему.
Компилятор gcc жалуется на vtable (которая, помимо прочего, используется для классов с виртуальными функциями). Правила, которые он использует, задокументированы (см. docs ):
Если класс объявляет какие-либо не встроенные, нечистые виртуальные функции, первая выбирается в качестве «ключевого метода» для класса, и vtable генерируется только в блоке трансляции, где определен ключевой метод.
Теперь версия Alexey вашего класса определяет не встроенную, нечистую виртуальную функцию accept . Таким образом, gcc откладывает создание таблицы Land vtable до тех пор, пока не увидит определение Land :: accept . Добавьте это и посмотрите, работает ли это. Или, как говорит Николаз, просто сделайте это чисто виртуальным.
Ну, я не хочу «решать» проблему. Я хочу понять, что не так и почему
Привыкайте отделять объявления от определений. За исключением специального случая шаблонов, C ++, как правило, работает лучше.
Я не писал сложных Программа на C ++ давно работает, но, если я правильно помню, вы должны вырезать скелет этих классов в файле .h
с тем же именем, что и этот файл .c
. Затем включите его в этот .c
файл.
Надеюсь, это поможет.
Дайте объявление типа всего класса перед его использованием .. Я думаю, это сработает.