Почему не объявление объявления класса работает, когда класс включен в другой класс

Это компилирует

#include "Sprite.h"

class GameObject
{
  public:
      int x, y, w, h;
      Sprite sprite;
  public:
    GameObject();
    GameObject(int _x, int _y, int _w, int _h);
    virtual ~GameObject();
};

Это не

class Sprite;

class GameObject
{
  public:
      int x, y, w, h;
      Sprite sprite;
  public:
    GameObject();
    GameObject(int _x, int _y, int _w, int _h);
    virtual ~GameObject();
};

Я знаю, что могу переслать объявление и использовать указатель для Sprite, но почему здесь не работает пересылка объявлений. Не "класс Sprite"; говорит что спрайт существует? Я пытаюсь #include столько классов в .cpp и избегать его в .h любой ценой. Также классы не включают друг друга, поэтому нет необходимости использовать Sprite *. Я полагаю, что мое понимание того, что такое объявление вперед, неверно или что-то в этом роде, потому что я не вижу причины, по которой это не работает.

Заранее спасибо.

Ответы на вопрос(3)

Sprite не может бытьнеполный тип здесь, потому что размер и расположение этого должны быть известны как нестатический член классаGameObject.

(Обратите внимание на третий)

Любой из следующих контекстов требует классаT быть завершенным:

definition or function call to a function with return type T or argument type T;
definition of an object of type T;
declaration of a non-static class data member of type T;
new-expression for an object of type T or an array whose element type is T;
lvalue-to-rvalue conversion applied to a glvalue of type T;
an implicit or explicit conversion to type T;
a standard conversion, dynamic_cast, or static_cast to type T* or T&, except when converting from the null pointer constant or from a pointer to void;
class member access operator applied to an expression of type T;
typeid, sizeof, or alignof operator applied to type T;
arithmetic operator applied to a pointer to T;
definition of a class with base class T;
assignment to an lvalue of type T;
a catch-clause for an exception of type T, T&, or T*.

С другой стороны, если вы объявите его как указатель или ссылку, неполный тип будет в порядке, и прямое объявление будет разрешено.

Решение Вопроса

Притворись, что ты компилятор. Не имея полной декларацииSprite в вашем распоряжении, как можно определить, является лиSprite только один байт или сто тысяч байт?

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

 πάντα ῥεῖ26 июл. 2016 г., 04:23
@DrunkBearzz Да!
 Drunk Bearzz26 июл. 2016 г., 04:25
Круто, это подводит итог, я тоже кое-что узнал об указателях
 Drunk Bearzz26 июл. 2016 г., 04:23
Таким образом, причина, по которой он работает с указателями, заключается в том, что единственное, что нужно знать указателю, это то, что размер адреса в памяти всегда одинаков?

Прямые объявления работают только со ссылками или указателями, если тип указан в объявлении зависимого класса.

class Sprite;

class GameObject
{
  public:
      int x, y, w, h;
      Sprite* sprite; // <<<<
  // or Sprite& sprite;
  public:
    GameObject();
    GameObject(int _x, int _y, int _w, int _h);
    virtual ~GameObject();
};

Забота, чтобы включитьSprite.h файл в вашей реализации, и в идеале инициализируйте член в вашей реализации конструктора (для ссылки это будет строго необходимо).

 Drunk Bearzz26 июл. 2016 г., 04:25
Теперь я понял, спасибо.

Ваш ответ на вопрос