Проблема с C ++ или Visual Studio 2010 - PullRequest
0 голосов
/ 31 января 2012

Через некоторое время я снова поднимаю C ++, и у меня возникают проблемы с пониманием определенного поведения. Я не знаю, если это ошибка в VS 2010 или просто C ++. Я работаю над школьным проектом, так что простите за «нелепость» программы. Сначала я просто опубликую соответствующие файлы и их содержимое:
BarFly.h:

#ifndef PJ_BARFLY_H
#define PJ_BARFLY_H

#include "BarFlyOwnedStates.h"
#include "BaseGameEntity.h"
#include "FSM\StateMachine.h"

class BarFly : public BaseGameEntity {

private:
  StateMachine<BarFly>* state_machine;

public:

  BarFly(int id);

};

#endif // PJ_BARFLY_H

BarFlyOwnedStates.h:

#ifndef PJ_BARFLYOWNEDSTATES_H
#define PJ_BARFLYOWNEDSTATES_H

#include "BarFly.h"
#include "FSM/State.h"

class BarFly; // << Line A <<

class CarousingState : public State<BarFly>
{

public:

  static CarousingState *Instance();

  // Some non-relevant functions

};

#endif // PJ_BARFLYOWNEDSTATES_H

BarFly.cpp:

#include "BarFly.h"


BarFly::BarFly(int id) : BaseGameEntity(id) {
  state_machine = new StateMachine<BarFly>(this);
  state_machine->SetCurrentState(CarousingState::Instance()); // << Line B <<
}

Хорошо, поэтому мой вопрос: зачем мне включать строку A? Когда я пропускаю это, VS жалуется на строку B, говоря, что она не распознает CarousingState * как штат <BarFly>*. Любые отзывы приветствуются.

Ответы [ 4 ]

3 голосов
/ 31 января 2012

Проблема в том, что у вас круговая зависимость заголовка; "BarFly.h" и "BarFlyOwnedStates.h" каждый пытается включить друг друга. В результате, когда вы включаете "BarFly.h", включающие охранники означают, что определение BarFly приходит после , а CarousingState, поэтому BarFly не было объявлено в точке, в которой оно используется в качестве аргумента шаблона.

Строка A - это «предварительное объявление» (или просто «объявление»); он объявляет, что класс существует, но не определяет класс. Пока класс не определен, он известен как «неполный тип» и может использоваться в некоторых ситуациях.

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

В этом случае похоже, что вы можете удалить #include "BarFlyOwnedStates.h" из BarFly.h, и в зависимости от того, что State делает с аргументом шаблона, вы также можете удалить #include "BarFly.h" из BarFlyOwnedStates.h (сохраняя предварительная декларация по строке А). Вам нужно будет включить оба заголовка из исходного файла.

3 голосов
/ 31 января 2012

У вас есть два заголовочных файла, которые включают друг друга. Это не работает.

Ваш включенный охранник скроет класс во втором файле. Вот почему вам нужна строка A. Если этого достаточно для компиляции кода, просто удалите include в верхней части этого заголовка.

Файл cpp, с другой стороны, должен включать все используемые им заголовки.

1 голос
/ 31 января 2012

Это, вероятно, связано с круговой зависимостью, которую вы установили между BarFly и BarFlyOwnedStates.Попробуйте поместить #include "BarFly.h" в BarFlyOwnedStates.cpp вместо заголовка.

0 голосов
/ 31 января 2012

Это называется предварительным объявлением.Строка A сообщает компилятору о синтаксическом анализе BarFlyOwnedStates.h: чтобы не беспокоиться, будет класс с именем BarFLy, который вы обещаете определить последним.

В противном случае BarFlyOwnedStates.h: должен будет включать barfly.h, который будет представлятькруговая зависимость.

ps вам нужно, чтобы #include "BarFlyOwnedStates.h" и #include "BaseGameEntity.h" были включены в BarFly.h?Лучше использовать декларацию форварда класса, чтобы свести к минимуму включение заголовков в другие заголовки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...