Ошибка C2079, в каком порядке определяются классы - PullRequest
3 голосов
/ 26 сентября 2010

Я получаю ошибку компилятора с этим заголовочным файлом:

#ifndef GAME1_H  
#define GAME1_H  
#include "GLGraphics.h"  
#include "DrawBatch.h"  
class GameComponent;  
class Game1 {  
private:  
    GLGraphics graphics;  
 GameComponent components;
 void updateDelegates();  
 void Run();  
};  

class GameComponent {  
private:  
 static int index;  
protected:  
 Game1 game;  
public:  
 GameComponent();  
 GameComponent(Game1 game);  
 void Update(int);  
 void Dispose();  
};  

class DrawableGameComponent: public GameComponent  
{  
private:  
 GLGraphics graphics;  
 DrawBatch drawBatch;  
public:   
 DrawableGameComponent();  
 DrawableGameComponent(Game1);  
 void Draw();  
};  

#endif

Я вижу проблему в том, что Game1 требуется полное определение GameComponent, а GameComponent требуется полное определение Game1У меня было слишком много проблем, когда они были в разных заголовках, поэтому они вместе.Есть ли способ сделать это без полного изменения реализации одного из классов?

Спасибо!

Ответы [ 3 ]

10 голосов
/ 26 сентября 2010

Подумайте о памяти компьютера на секунду здесь.

class B;

class A {
    byte aa;
    B ab;
};

class B {
    byte bb;
    A ba;
};

A x;

Теперь вопрос, на который должен ответить компилятор: Сколько места я должен зарезервировать для x?

Посмотрим.Первый байт x равен byte aa;.Достаточно просто.Это 1 байт.
Далее идет B ab;.Давайте посмотрим, что там.
Первый байт x.ab - это byte bb;.Пока это 2 байта для x.
Далее, это A ba;.Давайте посмотрим, что там.
Первый байт x.ab.ba - это byte aa;.Пока это 3 байта для x.
И так далее, и так далее до бесконечности.
Насколько велика x?Правильный ответ, конечно, *** OUT OF CHEESE ERROR ***.

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


Вот диаграмма содержания x в этом примере:
Диаграмма http://i56.tinypic.com/28c0oiq.png


ОБНОВЛЕНИЕ

Видимо, я забыл включить решение здесь.Теперь, когда вы понимаете, в чем проблема, решение должно быть довольно простым.Используйте указатели. Либо используйте указатель от A до B, и пусть B включает A, как это уже делает, или наоборот, или два указателя.Тогда у вас не будет циклического включения - если B не содержит копию A, а просто указатель на нее, это решает всю проблему здесь.

4 голосов
/ 26 сентября 2010

Чтобы сделать то, что вы пытаетесь, вам нужно иметь указатель на один из ваших классов, а не на членство в нем.

Например:


class A;
class B;
class A {
   B b;
};

class B {
   A a;
};

Это не может работать. Это вызывает круговую структуру. Конструктор для A будет вызывать конструктор для B, который вызывает конструктор для A и т. Д. Бесконечно.

Вместо этого попробуйте:


class A;
class B;
class A {
   B *b;
};

class B {
   A *a;
};

Слово предупреждения, хотя. Если вы что-то настраиваете таким образом, вполне вероятно, что ваш дизайн имеет недостатки. Вам следует пересмотреть, как вы решаете свою проблему.

1 голос
/ 26 сентября 2010

С риском быть не по теме: вы можете сделать это в C #, но если вложенные элементы не все загружаются по требованию, вы получите немедленный сбой при первом создании любого из них.

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