Sich gegenseitig referenziernde Objekte



  • Hallo!

    Folgendes Problem:
    Ich habe eine Region die Zeiger auf Instanzen von Pixel haben. Jedes Pixel soll wiederum einen Zeiger auf die zugehörige Region haben.

    Code so weit:

    #ifndef Region_h
    #define Region_h
    #include <cstddef>
    #include <list>
    #include "Pixel.h"
    
    using namespace std;
    
    namespace RegionSegmentation
    {
    	class Region
    	{
    	private:
    		 list<Pixel *> pixellist;
    	public:
    		Region() {};
    		~Region() {};
    
    	};
    }
    #endif
    
    #ifndef Pixel_h
    #define Pixel_h
    #include <cstddef>
    #include "Region.h"
    
    namespace RegionSegmentation
    {
    	class Pixel
    	{
    	public:
    	   unsigned int x, y;
    	   Region* owner;
    	   Pixel() { x = 0 ; y = 0; owner=NULL;};
    	   Pixel(unsigned int m, unsigned int n, Region* reg) 
    {x = m ; y = m; owner=reg;};
    	   ~Pixel();
    	};
    
    }
    #endif
    


  • Du kannst Klassen unvollständig vordeklarieren.

    class Pixel;
    


  • Der Beitrag wurde gepostet bevor ich fertig war. Nächster Versuch. Kann vielleicht jemand den ersten Beitrag löschen?
    ###############################################################
    Hallo!

    Folgendes Problem:
    Ich habe eine Region die Zeiger auf Instanzen von Pixel haben. Jedes Pixel soll wiederum einen Zeiger auf die zugehörige Region haben.

    Code so weit:
    C/C++ Code:

    #ifndef Region_h
    #define Region_h
    #include <cstddef>
    #include <list>
    #include "Pixel.h"
    
    using namespace std;
    
    namespace RegionSegmentation
    {
        class Region
        {
        private:
             list<Pixel *> pixellist;
        public:
            Region() {};
            ~Region() {};
    
        };
    }
    #endif
    
    #ifndef Pixel_h
    #define Pixel_h
    #include <cstddef>
    #include "Region.h"
    
    namespace RegionSegmentation
    {
        class Pixel
        {
        public:
           unsigned int x, y;
           Region* owner;
           Pixel() { x = 0 ; y = 0; owner=NULL;};
           Pixel(unsigned int m, unsigned int n, Region* reg) 
                                        {x = m ; y = m; owner=reg;};
           ~Pixel();
        };
    
    }
    #endif 
    
    main.cpp
    #include <iostream>
    
    using namespace std;
    
    int main()
    { 
      char a;
      cin >> a;
      return 0;
    }
    

    Solange ich in main.cpp nicht "Pixel.h" und/oder "Region.h" per include einfüge kommen keine Fehlermeldungen. So bald ich das mache gibts Probleme.
    Das kann ich zwar auch nachvollziehen, aber ich weiß nicht wie es richtig geht.



  • SeppSchrot schrieb:

    Du kannst Klassen unvollständig vordeklarieren.

    class Pixel;
    

    Oh je, die Antwort kam aber schnell. 🙂
    Uhm, könntest Du das jetzt noch mal für ne Anfängerin ausführlicher erläutern bitte?!



  • Beispiel: wenn du zuerst die region.h includierst, wird die as allererstes die pixel.h includieren - der Text sieht, nachdem der Präprozessor die includes abgearbeitet hat, für den Compiler etwa so aus:

    //hier beginnt der kram aus region.h
    
    //der code aus <cstddev>
    //der code aus <list>
    
    //jetzt der code aus pixel.h verarbeitet:
      //<stddev> wird dank include-guard nicht nochmal eingebunden
      //region.h wird dank include-guard nicht nochmal eingebunden
    
    namespace RegionSegmentation
    {
        class Pixel
        {
        //...
        Region* owner            //Was ist denn bitte Region??
        };
    }
    
    //ende des codes aus pixel.h, weiter gehts mit region.h
    
    using namespace std;
    
    namespace RegionSegmentation
    {
        class Region
        {
        private:
             list<Pixel *> pixellist; //pixel ist bekannt, da ja oben der code steht
        };
    }
    

    Wegen der include-guards kommts bei wechselseitigen Abhängigkeiten also dazu, dass die eine Klasse die andere noch nciht kennt (wäre genauso, wenn du beide Klassendefinitionen in einen header schreibst. Dafür gibts doe sog. forward-deklaration:

    class Region; //keine Definition, sondern nur Deklaration,
                  //dem Compiler wird nur klargemacht, dass es die Klasse gibt
                  //mehr brauch er nicht wissen für die Klassendefinition
    
    class Pixel
      {
      //... hier kommt die Definition von Pixel
      // es ist jetzt bekannt, dass es eine class Region gibt
      };
    
    class Region
      {
      //verwendung von Pixel auch kein Problem mehr.
      };
    

    So. Wie sieht das ganze nun in geteilten headern aus? nun, da du nicht weißt, welcher header zuerst übersetzt wird, musst du wohl in beiden die forward-deklaration machen:
    region.h:

    class Pixel;
    
    class Region
      {
      //... usw.
      };
    

    pixel.h:

    class Region;
    
    class Pixel
      {
      //... usw.
      };
    

    noch eine Sache zu den includes:
    Die region.h braucht die Pixel.h nicht zu includieren, wenn sie nicht auf die Klasse zugreift. Solang Pixel nur als Datenmember, Parameter und/oder Rückgabewert auftaucht, reicht es, die forward-Deklaration reinzuschreiben. Umgekehrt natürlich genauso.
    Wenn auch bei der Implementierung (also in der region.cpp) nur mit den Zeigern rumgefuhrwerkt wird, brauchst du auch da nicht wissen, wie das interface der Klasse Pixel aussieht. Theoretisch könntest du dann die Klasse Pixel komplett neu schreiben, ohne die Klasse Region neu kompilieren zu müssen.
    In dem Fall includiert man dann beide header schlicht in die main.cpp, und das reicht dann schon.



  • Danke für die super gute Erklärung!! 👍
    Jetzt geht es. 🙂


Anmelden zum Antworten