Дважды включить решение? - PullRequest
       12

Дважды включить решение?

3 голосов
/ 05 октября 2011

В C ++ у меня проблема с двойным включением:

Файл stuffcollection.h

#pragma once
#ifndef STUFFCOLLECTION_H
#define STUFFCOLLECTION_H

#include "Stage.h"

class Stuffcollection {
    public:
        bool myfunc( Stage * stage );
};

#endif // STUFFCOLLECTION_H

Файл stage.h:

#pragma once
#ifndef STAGE_H
#define STAGE_H

#include "Stuffcollection.h"

class Stage {
    // stuffcollection used in stage.cpp
};

#endif // STAGE_H

Ошибка компилятора:

\Stuffcollection.h|(line were bool myfunc is declared)|error: 'Stage' has not been declared| ||=== Build finished: 1 errors, 0 warnings ===|

Может кто-нибудь объяснить, почему это происходит и как это можно решить? Я уже использую include guards и директиву препроцессора pragma, и она просто не работает.

(Если я удаляю #include "Stuffcollection.h" из stage.h и закомментирую соответствующие строки, которые используют его в stage.cpp, остальная часть моего кода работает нормально. Действительно, только при включении Stuffcollection в stage он внезапно перестает работать .)

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

РЕДАКТИРОВАТЬ : Я следовал предложенному, и теперь проблема в invalid use of incomplete type, т. Е. В то время как данные ответы решают проблему круговой зависимости, они не решают проблему, с которой я имею дело. Моя проблема продолжается в Круговые зависимости / Неполные типы .

РЕДАКТИРОВАТЬ : Теперь оба решены.

Ответы [ 3 ]

13 голосов
/ 05 октября 2011

У вас есть Круговая зависимость .Вместо этого используйте Форвардное объявление в Stuffcollection.h

#pragma once
#ifndef STUFFCOLLECTION_H
#define STUFFCOLLECTION_H

//#include "Stage.h"      //<------------------Don't Do This
class Stage;              //<------------------Do This

class Stuffcollection {
    public:
        bool myfunc( Stage * stage );
};

#endif // STUFFCOLLECTION_H

Обоснование:
Вы можете использовать форвардное объявление в приведенном выше фрагменте, потому что, Stuffcollection.h использует толькоуказатель на Stage.

Объяснение:
Используя предварительное объявление класса Stage, компилятор не знает ни его состава, ни членов внутри него, компилятор знает только, что Stageэто type.Таким образом, Stage является Неполным типом для компилятора.С незавершенными типами, Нельзя создавать объекты этого или делать что-либо, что требует компилятору знать макет Stage или больше, чем тот факт, что Stage это просто тип.Поскольку указатели на все объекты требуют одинакового распределения памяти, вы можете использовать прямое объявление, просто ссылаясь на Stage в качестве указателя.

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

Подробнее:
Когда использовать предварительные декларации?

5 голосов
/ 05 октября 2011

Это круговая зависимость. Не делай их. Эту проблему можно решить, заменив #include "Stage.h" в stuffcollection.h на предварительное объявление Stage (т.е. class Stage;).

3 голосов
/ 05 октября 2011

Вместо #include вы можете использовать предварительные объявления, например class Stage; и class Stuffcollection.Преимущество также заключается в уменьшении зависимостей.

...