Круговые зависимости / неполные типы - PullRequest
4 голосов
/ 05 октября 2011

В C ++ у меня проблема с циклическими зависимостями / неполными типами. Ситуация выглядит следующим образом:

Stuffcollection.h

#include "Spritesheet.h";
class Stuffcollection {
    public:
    void myfunc (Spritesheet *spritesheet);
    void myfuncTwo ();
};

Stuffcollection.cpp

void Stuffcollection::myfunc(Spritesheet *spritesheet) {
    unsigned int myvar = 5 * spritesheet->spritevar;
}
void myfunc2() {
    //
}

Spritesheet.h

#include "Stuffcollection.h"
class Spritesheet {
    public:
    void init();
};

Spritesheet.cpp

void Spritesheet::init() {
    Stuffcollection stuffme;
    myvar = stuffme.myfuncTwo();
}
  • Если я сохраню включения, как показано выше, я получу ошибку компилятора spritesheet has not been declared в Stuffcollection.h (строка 4 в выше). Я понимаю, что это связано с круговой зависимостью.
  • Теперь, если я поменяю #include "Spritesheet.h" на Форварда Декларация class Spritesheet; в Stuffcollection.h, я получаю ошибка компилятора invalid use of incomplete type 'struct Spritesheet' в Stuffcollection.cpp (строка 2 выше).
  • Аналогично, если я изменю #include "Stuffcollection.h" на class Stuffcollection; в Spritesheet.h, я получу ошибку компилятора aggregate 'Stuffcollection stuffme' has incomplete type and cannot be defined в Spritesheet.cpp (строка 2 выше).

Что я могу сделать, чтобы решить эту проблему?

Ответы [ 3 ]

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

Вы должны включить Spritesheet.h в Stuffcollection.cpp
Просто используйте предварительное объявление в заголовочном файле, а не в файле cpp, которое решает циклическую зависимость заголовочного файла. Исходный файл фактически не имеет циклической зависимости.

Stuffcollection.cpp необходимо знать полный макет класса Spritesheet (поскольку вы разыменовываете его), поэтому вам нужно включить заголовок, который определяет класс Spritesheet в этом файле.

Из вашего предыдущего Q здесь я считаю, что класс Stuffcollection используется в объявлении класса заголовочного файла Spritesheet и, следовательно, в предложенном выше решении.

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

Используйте эту форму для ваших вложений:

Stuffcollection.h

#ifndef STUFFCOLLECTION_H_GUARD
#define STUFFCOLLECTION_H_GUARD
class Spritesheet;
class Stuffcollection {
  public:
  void myfunc (Spritesheet *spritesheet);
  void myfuncTwo ();
};
#endif

Stuffcollection.cpp

#include "Stuffcollection.h"
#include "Spritesheet.h"

void Stuffcollection::myfunc(Spritesheet *spritesheet) {
  unsigned int myvar = 5 * spritesheet->spritevar;
}

void Stuffcollection::myfuncTwo() {
  //
}

Spritesheet.h

#ifndef SPRITESHEET_H_GUARD
#define SPRITESHEET_H_GUARD
class Spritesheet {
  public:
  void init();
};
#endif

Spritesheet.cpp

#include "Stuffcollection.h"
#include "Spritesheet.h"

void Spritesheet::init() {
  Stuffcollection stuffme;
  myvar = stuffme.myfuncTwo();
}

Общие правила, которым я следую:

  • Не включайте включение из включения, чувак.Предпочитаю предварительные декларации, если это возможно.
    • Исключение: включение системы включает в себя все, что вы хотите
  • Пусть CPP включает все, что ему нужно, не полагаясь на H рекурсивно включая его файлы.
  • Всегда использоватьвключите охрану.
  • Никогда не используйте pragma
2 голосов
/ 05 октября 2011

Spritesheet.h необязательно включать Stuffcollection.h, так как Stuffcollection не используется в объявлении класса Spritesheet. Переместите эту строку включения на Spritesheet.cpp, и все будет в порядке.

...