2012-06-11 7 views
12

Ich habe eine wissenschaftliche Simulationsplattform von Java in C++ konvertiert. Ich habe versucht, das Design so gut wie möglich zu halten, wie bei der vorherigen Implementierung. In Java werden aufgrund der späten Bindung zirkuläre Abhängigkeiten zur Laufzeit aufgelöst. Circular Abhängigkeiten haben jedoch in C++ eine Hölle von Chaos geschaffen.C++, zwei Klassen mit gemeinsamen Bedürfnissen

  1. Gibt es ein automatisiertes Tool, das die zirkulären Includes und Referenzen analysiert und auflistet? (Visual Studio 2010 gibt nur eine große Liste von unsinnigen Fehlern aus).

  2. Ich habe versucht, Forward-Referenzen wo immer möglich zu verwenden. Jedoch benötigen in einigen Fällen beide Klassen Funktionalität der anderen Klasse (d. H. Aufruf von Methoden, die es unmöglich machen, Vorwärtsreferenz zu verwenden). Diese Bedürfnisse gibt es in der Logik und wenn ich das Design radikal verändere, werden sie nicht mehr reale Interaktionen repräsentieren.

    Wie können wir zwei Klassen implementieren, die die Methoden und den Status des jeweils anderen benötigen? Ist es möglich, sie in C++ zu implementieren?

Beispiele:

  • Beispiel 1: Ich habe eine Klasse "World", die Objekte des Typs "Agent" erstellt. Der Agent muss World-Methoden aufrufen, um Informationen über seine Umgebung zu erhalten. World muss auch über Agenten iterieren und ihre "run" -Methode ausführen und ihren Status abrufen (Statusaktualisierungen können möglicherweise umgekehrt durchgeführt werden, um diesen Abschnitt des Problems zu lösen, aber nicht die run-Methode).
  • Beispiel 2: Agenten erstellen eine Sammlung ihrer "Absichten". Jeder Agent muss seine Absichten durchlaufen und den Intentionsstatus ausführen/aktualisieren/lesen. Intentionen müssen auch Informationen über die Umgebung durch Agenten erhalten (wenn sie direkt über "Welt" gemacht werden, werden sie wieder komplexe Kreise erzeugen) und auch Informationen über den Agenten selbst.

Die untenstehende Abbildung zeigt eine Untergruppe von Klassen und einige ihrer Methoden und Eigenschaften:

sub-set of classes, and some of their methods and properties

+0

Wenn Sie Probleme mit Fehlern haben, könnten Sie immer eine Frage mit diesen Fehlern (wörtlich bitte) posten und jemand wird Ihnen höchstwahrscheinlich helfen können. Auch diese Fehler können für Sie Unsinn sein, aber nicht für jemand anderen. Es ist auch sehr schwierig, Fragen zu beantworten, ohne etwas Code zu sehen, und dazu empfehle ich Ihnen, http://sscce.org/ zu lesen. –

+0

Joachim, Sie sind die Art von Fehlern, die in zirkulären Abhängigkeitsfällen generiert werden. Klassen können nicht identifiziert werden. 'code' 1> e: \ programmierung \ cprojt \ actiondb11 \ actiondb \ base \ world.h (35): Fehler C2143: Syntaxfehler: fehlt ',' vor '*' 1> e: \ programing \ cprojt \ actiondb11 \ actiondb \ base \ world.h (36): Fehler C2061: Syntaxfehler: Bezeichner 'Agent' 1> e: \ Programmierung \ cprojt \ actiondb11 \ actiondb \ base \ world.h (50): Fehler C2065: ' Agent ': nicht deklarierter Bezeichner – wmac

+1

Das Posten des Codes ist viel hilfreicher als das Posten der Fehler. Posting * beide * ist am besten. –

Antwort

17

Ich sehe nicht, wie Vorwärtsdeklarationen nicht für Sie arbeiten. Es sieht aus wie Sie brauchen so etwas wie:

World.h:

#ifndef World_h 
#define World_h 

class Agent; 

class World 
{ 
    World(); 
    void AddAgent(Agent* agent) { agents.push_back(agent); } 
    void RunAgents(); 
private: 
    std::vector<Agent*> agents; 
}; 

#endif 

Agent.h:

#ifndef Agent_h 
#define Agent_h 

class World; 
class Intention; 

class Agent 
{ 
    Agent(World& world_): world(world_) { world.AddAgent(this); } 
    status_t Run(); 
private: 
    World& world; 
    std::vector<Intention*> intentions; 
}; 

#endif 

World.cc:

#include "World.h" 
#include "Agent.h" 

void World::RunAgents() 
{ 
    for(std::vector<Agent*>::iterator i = agents.begin(); i != agents.end; ++i) 
    { 
     Agent& agent(**i); 
     status_t stat = agent.Run(); 
     // do something with stat. 
    } 
} 

// ... 

Agenten.cc:

+1

Ich werde versuchen, Referenzen erneut mit Include-Dateien am Anfang der cpp-Dateien zu versuchen. Ich denke, das würde hoffentlich Probleme lösen. – wmac

+3

Auch wenn dies in der Sprache nicht erforderlich ist, empfiehlt es sich, alle Includes an den Anfang der Datei zu setzen, damit jemand, der Ihren Code liest, seine Abhängigkeiten schnell erkennen kann. –

+1

Gibt es eine Lösung, wenn Sie nicht nur Referenzen, sondern tatsächliche Instanzen von Typ A in Typ B haben und umgekehrt? Ich bekomme einen "unvollständigen Typ" Fehler vom Compiler, der Sinn macht. Aber gibt es einen Weg um es herum? –

3

Sie können lösen das Problem mit nur vorwärts Erklärungen, aber Sie wahrscheinlich didn‘ t trennen Sie die Implementierung von der Deklaration der Klasse.

Wenn Sie Methoden aus der Klasse aufrufen müssen, ist ein vollständiger Typ erforderlich, weshalb Sie die Datei einschließen müssen. Sie können die Datei in eine cpp (Implementierungsdatei) einschließen, ohne sich über zirkuläre Abhängigkeiten Gedanken machen zu müssen.

+0

Danke Luchian. Meine Implementierung ist separat, aber ich habe die Include-Dateien nicht in die cpp-Dateien verschoben. – wmac

Verwandte Themen