kostenloser Webspace werbefrei: lima-city


Ringschluss in Klassen ohne Fehlermeldung

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    dustboy

    Kostenloser Webspace von dustboy

    dustboy hat kostenlosen Webspace.

    Hi.
    Ich muss für mein Aktuell laufendes Projekt von einer Klasse aus auf eine andere zugreifen, die wiederum auf diese Klasse zugreift. Also etwas in diese Richtung:

    class Klasse1
    {
       Klasse2 *klasse2;
    };
    
    class Klasse2
    {
       Klasse 1 *klasse1;
    }
    
    int main()
    {
       Klasse1 klasse1;
       return 0;
    }


    Dieser Code erzeugt eine Fehlermeldung, da ein Ringschluss besteht. Genau diesen benötige ich aber.
    Gibt es einen weg etwas ähnliches zu bauen wie mein code oben, der aber keinen Fehler erzeugt?
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. du darfst in klasse2 kein neues objekt von klasse1 erzeugen, sondern musst das schon bestehende in der main-methode erzeugte objekt verwenden. dann hast du deinen ringschluss, der aber nicht endlos ist. so wie du es jetzt hast, erzeugt klasse1 ein neues objekt von klasse2, diese wiederum erzeugt ein objekt von klasse1 und so weiter. am ende läuft der RAM mit objekten von klasse1 und klasse2 über.

    als code könnte das dann in etwa so aussehen:
    class Klasse1
    {
       Klasse2 *klasse2(this);
    }
    
    class Klasse2
    {
       Klasse1 *klasse1;
       public Klasse2(Klasse1 klasse1)
       {
          this.klasse1 = klasse1;
       }
    }
    
    int main()
    {
       Klasse1 klasse1;
       return 0;
    }


    mfg
  4. Autor dieses Themas

    dustboy

    Kostenloser Webspace von dustboy

    dustboy hat kostenlosen Webspace.

    danke erstmal für deine Antwort. Leider löst das mein Problem nicht wirklich. Aber scheinbar muss ich etwas detailierter erläutern, was ich will.

    Ich programmiere ein Echtzeitstrategiespiel. Für die Einheitenverwaltung habe ich eine Klasse Instanzenpool, die dafür zuständig ist die Zeiger auf alle Instanzen abzuspeichern, neue Einheiten zu erschaffen, etc.

    Hier mal eine abgespeckte Version:

    enum Einheitentypen
    {
       TYP_MAGIER,
       TYP_GOLEM,
       TYP_ARBEITER
    }
    
    class Instanzenpool
    {
    private:
       Einheit **einheiten;
    public:
       Instanzenpool()
       {
          einheiten = new Einheit*[500];
          for (int i = 0; i < 500; i++)
          {
             einheiten[i] = NULL;
          }
       }
       int neueEinheit(Einheitentypen typ)
       {
          int id;
          for (id = 0; einheiten[id] != NULL; id++)
          {
          }
          switch (typ)
          {
             case TYP_MAGIER:
                einheiten[id] = new Magier;
                break;
             case TYP_GOLEM:
                einheiten[id] = new Golem;
                break;
             case TYP_ARBEITER:
                einheiten[id] = new Arbeiter;
                break;
          }
          return id;
       }
       void leftMouse(int x, int y)
       {
          //Hier wird ausgewertet welche Einheit angeklickt wurde und dann dieser ein Entsprechendes Signal gesendet
       }
    };
    
    static Instanzenpool instanzenpool = new Instanzenpool;


    Sowohl die Klasse Arbeiter, als auch die Klasse Magier erben jeweils von der Klasse Einheit.

    Soll der Magier einen Erdgolem beschwören können benötigt also die Klasse Magier folgende Methode:

    void golemErschaffen()
    {
       instanzenpool->neueEinheit(TYP_GOLEM);
    }


    Damit haben wir dann den Ringschluss. Leider kann ich den Golem auch nicht einfach in der Klasse des Magiers abspeichern, da ja die Klasse Instanzenpool die komplette verwaltung der Mausklicks etc. übernimmt.
  5. Du musst einfach an die Klasse Magier das Objekt der Klasse Instanzenpool mitübergeben und dort dann als Instanzvariable speichern.

    also:
    einheiten[id] = new Magier(this);



    die Klasse Magier muss da so aussehen:
    class Magier
    {
      Instanzenpool pool;
      public Magier(Instanzenpool pool)
      {
        this.pool = pool;
      }
    
      golemErschaffen()
      {
        pool->neueEinheit(TYP_GOLEM);
      }
    }


    da Magier und Golem von Einheit abgeleitet sind, kannst du die Übergabe im Konstruktor gleich in Einheit einbauen, also:

    class Einheit
    {
      Instanzenpool pool;
      public Magier(Instanzenpool pool)
      {
        this.pool = pool;
      }
    }


    dann fällt die Instanzvariable pool aus der Klasse Magier natürlich weg.

    mfg
  6. Vielleicht könnte es Dein Problem lösen, wenn Du die beiden Klassen als Friends deklarierst?

    class KlasseA;
    class KlasseB;
    
    class KlasseA
    {
          private:
                int      a;
          public:
                KlasseA();
                ~KlasseB();
    
          friend class KlasseB;
    };
    
    class KlasseB
    {
          private:
                int      b;
          public:
                KlasseB();
                ~KlasseB();
                
          friend class KlasseA;
    };


    Damit kann KlasseA auf alle Eignenschaften von KlasseB zugreifen und umgekehrt.
  7. Autor dieses Themas

    dustboy

    Kostenloser Webspace von dustboy

    dustboy hat kostenlosen Webspace.

    Eure beiden Antworten zielen leider beide darauf ab auf den Zugriff auf die Klasse Instanzenpool zu ermöglichen. Diesen habe ich allerdings bereits ermöglicht - siehe Erster Quelltext letzte zeile:
    static Instanzenpool *instanzenpool = new Instanzenpool;

    Das Problem ist ja dass die Klasse Magier und die Klasse Instanzenpool auf sich gegenseitig verweisen, was einen Compilerfehler erzeugt.
  8. Wenn ich dich richtig verstanden habe, kann dich der Begriff "Vorwärtsdeklaration" weiterbringen. Damit kann man zwei Klassen gegenseitig bekannt machen, ohne dass der Compiler meckert. Kann ich dir mal kurz erläutern (wenn du nicht danach suchst, dann entschuldige bitte, habe die Beiträge hier nur ein wenig überflogen und nicht ganz gelesen).

    Zwei Klassen: Instanzenpool und Einheit. Jede hat eine Headerdatei und eine Cpp-Datei. Ich versuche es auf das minimalste zu beschränken. Mal sehen, ob ich es so aus dem Stegreif hinbekomme:

    // Instanzenpool.h
    
    class Instanzenpool {
       private:
          Einheit *einheit;
       public:
          Instanzenpool();
    }

    // Instanzenpool.cpp
    #include "instanzenpool.h"
    
    Instanzenpool::Instanzenpool() { }

    // Einheit.h
    
    class Instanzenpool;  // Hier die Klasse deklarieren
    
    class Einheit {
       private:
           Instanzenpool *instanzpool;   // Wichtig: Nur Pointer dieser Klasse erlaubt.
    }


    // Einheit.cpp
    #include "einheit.h"
    // Hier nun die Headerdatei bekannt machen, damit du alle Funktionen, etc. nutzen kannst:
    #include "instanzenpool.h"
    
    Einheit::Einheit( ) { }
  9. Autor dieses Themas

    dustboy

    Kostenloser Webspace von dustboy

    dustboy hat kostenlosen Webspace.

    Danke dir. Genau sowas hab ich gesucht =)
    Funktioniert prima - abgesehen von der Tatsache, dass ich beim Testausführen ein "Echtzeitstrategie.exe funktioniert nicht mehr" entgegengeschleudert bekomm - aber das ist eher ein anderes problem hehe

    Danke euch allen auch noch mal für eure Mühe
    MfG
    Dustboy
  10. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!