2016-07-26 24 views
2

Dies kompiliertWarum funktioniert nicht foward Deklaration der Klasse, wenn Klasse in eine andere Klasse enthalten ist

#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(); 
}; 

Dies gilt nicht

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(); 
}; 

Ich weiß, dass ich erklären und Zeiger verwenden, weiterleiten könnten Sprite, aber warum leitet die Deklaration hier nicht weiter. Nicht "Klasse Sprite;" erzählt, dass Sprite existiert? Ich versuche # so viele Klassen in .cpp einzuschließen und es in .h um jeden Preis zu vermeiden. Auch Klassen schließen einander nicht ein, so dass es nicht notwendig ist, Sprite * zu verwenden. Ich denke, dass mein Verständnis davon, was nach vorne deklarieren ist falsch oder etwas ist, weil ich keinen Grund sehe, warum das nicht funktioniert.

Vielen Dank im Voraus.

Antwort

3

Täuschen Sie vor, Sie sind der Compiler. Ohne eine vollständige Erklärung der Sprite zu Verfügung, wie ist es möglich zu bestimmen, ob die Sprite ist nur ein Byte groß, oder hunderttausend Bytes groß?

Sie müssen nicht viel über die Klasse wissen, wenn Sie nur einen Zeiger auf die Klasse benötigen (oder einen Verweis auf eine Klasse oder einige andere kleinere Dinge); Aber wenn Sie die Klasse tatsächlich verwenden müssen, reicht eine bloße Vorwärtsdeklaration nicht aus. Es ist nicht immer genug zu wissen, dass "Sprite existiert"; Manchmal ist es auch wichtig zu wissen, wie groß es ist. Und ohne eine vollständige Erklärung ist das nicht möglich.

+0

Der Grund, warum es mit Zeigern funktioniert, ist, weil der einzige Dingzeiger, der wissen muss, die Größe der Speicheradresse ist, die immer dieselbe ist? –

+0

@DrunkBearzz Yup! –

+0

Cool, das fasst es zusammen, ich lerne auch etwas über Zeiger, danke Mann –

2

Vorwärtsdeklarationen funktionieren nur mit Referenzen oder Zeigern, wenn der Typ in der abhängigen Klassendeklaration erscheint.

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(); 
}; 

Pflege der Sprite.h Datei in Ihrer Implementierung umfassen, und das Element in Ihrem Konstruktor Implementierung initialisieren idealerweise (ein Verweis würde erfordern, dass streng).

+0

Ich habe es jetzt, danke. –

1

Sprite kann nicht incomplete type hier sein, weil die Größe und das Layout davon als das nicht statische Mitglied der Klasse GameObject bekannt sein muss.

(Beachten Sie die Nummer 3.)

Jede der folgenden Kontexte erfordert Klasse T auf Vollständigkeit:

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

Auf der anderen Seite, wenn Sie es als Zeiger oder eine Referenz deklarieren , unvollständiger Typ ist in Ordnung und eine Vorwärtsdeklaration ist erlaubt.