2017-10-07 2 views
0

Was ich mache: Ich habe zwei Dateien: game.h und sound_controller.h. Beide haben Konflikte miteinander. game.h benötigt einen SoundController, während sound_controller.h ein Spiel benötigt, also enthalten beide die Header-Dateien des jeweils anderen.Unvollständiger Typ, aber ich verwende Vorwärtsdeklarationen?

Das Problem: game.h Linie 26:

error: field soundController has incomplete type 'SoundController' 

Ich habe sound_controller.h in game.h enthalten, aber es sagt der Typ ist unvollständig noch habe ich die Klasse SoundController erklärt . Also, wie repariere ich das?

Der Code:

game.h:

#pragma once 

/** 
    game.h 
    Handles highest level game logic 
*/ 

#include <SDL.h> 
#include <SDL_image.h> 
#include <SDL_ttf.h> 
#include <SDL_mixer.h> 

#include <iostream> 

#include "config.h" 
#include "sound_controller.h" 
#include "image_controller.h" 

#include <stdarg.h> 

class SoundController; //forward declaration 

class Game { 

    ImageController imageController; 
    SoundController soundController; 

    SDL_Window* window = NULL; 

    bool running; 


public: 
    Game(); 
    bool init(); 
    bool createWindow(); 

    void update(); 

    static void log(const char* format, ...); 

}; 

sound_controller.h:

#pragma once 

/** 
    sound_controller.h 
    Allows for manipulation with sound (sound effects and music) 
*/ 

#include "config.h" 
#include <SDL_mixer.h> 
#include "Game.h" 

class Game; //forward declaration 

class SoundController { 

    bool init(); 
    bool load_sound(); 
    bool load_music(); 

    void music_play(); 
    void music_pause(); 
    void music_stop(); 

}; 

sound_controller.cpp Spiel verwendet, weil es Game.h statische Funktion aufruft: log .

EDIT:

entfernt "# include game.h" von sound_controller.h. Jetzt bekommen einen anderen Fehler diesmal in sound_controller.cpp:

line 8 error: incomplete type 'Game' used in nested name specifier 

sound_controller.cpp:

#include "sound_controller.h" 

bool SoundController::init() { 
    bool success = true; 

    //Initialize SDL_mixer 
    if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { 
     Game::log("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError()); 
     success = false; 
    } 

    return success; 

} 

EDIT2:

Lösung war #include "game.h" in sound_controller setzen .cpp.

+1

Mögliches Duplikat von [Beheben von Buildfehlern aufgrund der zirkulären Abhängigkeit zwischen Klassen] (https://stackoverflow.com/questions/625799/resolve -build-Fehler-wegen-Kreis-Abhängigkeit-zwischen-Klassen) – SirGuy

Antwort

1

Sie haben eine zirkuläre Abhängigkeit - jede Ihrer Header-Dateien versucht, die andere zu enthalten; aber man kann nicht beides haben: Einer der beiden Header wird zuerst geparst, und wenn der Parser den ersten Header analysiert, weiß er (noch) nichts über den Inhalt des zweiten Headers (weshalb er sich darüber beschwert) "unvollständiger Typ").

Die einfache Lösung in diesem Fall wäre, die Zeile "#include Game.h" aus Ihrer sound_controller.h Datei zu entfernen.

+0

Also habe ich #include game.h entfernt, aber jetzt bekomme ich einen weiteren Fehler in sound_controller.cpp Ich habe den Code oben in meinem ersten Beitrag sowie die Error. –

+0

Sie müssen der Datei sound_controller.cpp ein "#include Game.h" hinzufügen. –

+0

Es hat funktioniert! Du schaukelst. –

0

Für mich scheinen Sie immer noch verloren zu sein. Lassen Sie uns den Testfall vereinfachen:

class A { 
public: 
    A(); 
    B b; 
}; 

class B { 
public: 
    B(); 
    A a; 
}; 

A::A() {;} 
B::B() {;} 

Wenn die Compiler-Figuren aus über A, der Compiler über sein Feld b des Typs B. A ist b ist ein Datenelement, dessen Speicher als A zugeordnet werden soll wissen muss instanziiert. Um zu wissen, es, Compiler dies muss:

class B { 
public: 
    B(); 
    A a; 
}; 

Ebenso für den Compiler, um herauszufinden, wie der Speicher sollte für B a zugeordnet werden, sollte der Compiler über A. wissen Somit ist es eine zirkuläre Abhängigkeit ist, und kann nicht gelöst werden.

Glücklicherweise hat Ihr SoundController kein Spiel, während das Spiel SoundController hat.Daher gibt es keine zirkuläre Abhängigkeit. Nur die Klasse SoundController {...} sollte vor dem Klassenspiel {...} kommen.

Wenn jedoch in meinem Beispiel A und B voneinander abhängig sind oder eine zirkuläre Abhängigkeit zwischen mehreren Klassen besteht, wäre dies ein Problem.

Um es zu lösen, hilft Forward-Deklaration selbst nicht, wenn der Feldtyp eine Klasse ist. Mit anderen Worten, wenn ein Speicher für das Feld zugewiesen und für das Feld ausgelegt werden sollte, wenn die Klasse selbst instanziiert wird, hilft die Vorwärtsdeklaration nicht. Es hilft nur, wenn der Feldtyp ein Zeiger oder Verweis auf eine andere Klasse ist. In meinem Beispiel funktioniert die Forward-Deklaration nur, wenn A's Feld B B * oder B & ist.

class A { 
public: 
    A(); 
    B* b; // whatever the pointer points to, the size of the pointer is given 
}; 

class B { 
public: 
    B(); 
    A a; // the compiler now can fine A from above 
}; 

Jetzt weiß der Compiler, wie viel Speicher er für A reserviert und wie das Speicherlayout aussieht. In diesem Fall muss der Compiler nichts über die Größe von B wissen. Es muss nur die Größe eines Zeigers kennen. Da das Speicherlayout von A gelöst ist, kann der Compiler das folgende B-Speicherlayout usw. lösen.

Verwandte Themen