当 class 包含在另一个 class 中时,为什么 class 的转发声明不起作用

Why doesn't foward declaration of class work when class is included in another class

这样编译

#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 转发声明和使用指针,但为什么转发声明在这里不起作用。 "class Sprite;" 不是说 Sprite 存在吗? 我在 .cpp 中尽可能多地尝试 #include 类 并不惜一切代价在 .h 中避免它。 此外 类 不相互包含,因此无需使用 Sprite*。 我想我对前向声明的理解是错误的,因为我看不出这是行不通的原因。

提前致谢。

假装你是编译器。如果没有完整的 Sprite 声明供您使用,如何确定 Sprite 是只有一个字节大还是十万字节大?

当您只需要指向 class 的指针(或对 class 的引用或其他一些次要事物);但是当你需要实际使用 class 时,仅仅前向声明是不够的。知道“Sprite 存在”并不总是足够的;有时也有必要知道它有多大。没有完整的声明,这是不可能的。

如果类型出现在依赖 class 声明中,则前向声明仅适用于引用或指针。

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 文件,并理想地在您的构造函数实现中初始化成员(引用将严格要求)。

Sprite这里不能是incomplete type,因为它的大小和布局必须知道是classGameObject的非静态成员。

(注意第三个)

Any of the following contexts requires class T to be complete:

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*.

另一方面,如果您将其声明为指针或引用,不完整的类型是可以的,并且允许向前声明。