ERLEDIGT!!! Problem bei Datapool (Singeltonklasse)



  • Hi,

    zuerst werd ich das Problem mal ein wenig beschreiben.

    Ich will einen Datenpool erstellen, auf den von jeder Klasse zugegriffen kann.
    Ich hab mir das so vorgestellt:
    es gibt

    - main.cpp für die hauptaufgaben
    - datapool.h und datapool.cpp für den datenpool
    - klasseA.h und klasseA.cpp: diese sollen einfach Funktionen und klassenvariablen beinhalten
    des Weiteren soll nur ein Objekt der Klasse existieren und über den Datenpool auf die Funktionen zugegriffen werden.

    z.b. Datapool::getDatapool()->getklasseA()->Funktion_von_klasseA();

    ich hoff ihr versteht was ich meine:

    bisher hab ich die folgenden Klassen programmiert:

    //Datapool.h
    #ifndef DATAPOOL_H_
    #define DATAPOOL_H_
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Datapool{
    	private:
    		static Datapool* datapool;
    
    	protected:
    		string name;
    		Datapool();
    	public:
    		static Datapool* getInstance();		
    		void setName(string tmp);
            string getName();
    };
    #endif /* DATAPOOL_H_ */
    
    #include "Datapool.h"
    
    Datapool* Datapool::datapool = 0;
    
    Datapool::Datapool(){
        name="";    
    }
    
    Datapool* Datapool::getInstance(){
    	if (datapool == 0 ){
    		datapool = new Datapool;
    	}
    	return datapool;
    }
    
    void Datapool::setName(string tmp){
    	name = tmp;
    }
    
    string Datapool::getName(){
    	return name;
    }
    

    So ist mein Grundgerüst des Datenpools auf den ich nun von der Main wenn ich #include "Datapool.h" mach mit Datapool::getInstance()->getName() z.b. zugreifen kann

    Wo ich nun hängen bleib ist, wenn ich eine weitere Klasse klasseA erstelle.
    In der Klasse selber soll auf den Datapool zugegriffen werden, jedoch soll die Klasse klasseA als Objekt im Datapool erscheinen, so dass ich nun von der main.cpp mit dem Befehl :
    Datapool::getInstance()->getklasseA()-> ... zugreifen kann

    // KlasseA.h
    #ifndef KlasseA_H_
    #define KlasseA_H_
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string>
    
    #include "Datapool.h"
    
    using namespace std;
    
    class KlasseA{
    
    	protected:
    		string name;
    	public:
    		KlasseA();
    		void setName(string n);
    		string getName();
    		void changeDatapoolName(string t);
    };
    #endif /* KlasseA_H_ */
    
    #include "KlasseA.h"
    
    KlasseA::KlasseA(){
       name = "KlasseA";
    }
    
    void KlasseA::setName(string n){
    	name = n;
    }
    
    string KlasseA::getName(){
    	return name;
    }
    
    void KlasseA::changeDatapoolName(string t){
    	  Datapool::getInstance()->setName(t);
    }
    

    Nun is die Frage wie ich die Klasse KlasseA im Datapool einbinden muss, damit ich z.B. von der main aus den Datapoolwert name mit :
    Datapool::getInstance()->getKlasseA()->changeDatapoolName("blub"); ändern kann.
    hoff das is einigermassen verständlich was ich meine



  • bin leider absoluter c++ noob hab das mal versucht so gut wie möglich zu lösen hoffe das macht was du willst?
    falls nicht nimm mir das nicht übel 😉

    #include <iostream>
    using namespace std;
    
    class Datapool{
    	private:
    		string name;
    		class klasseA{
                protected:
                    string name;
                public:
                    void setName(string n){
                    	this->name = n;
                    };
                    string getName(){
                    	return name;
                    };
                    void changeDatapoolName(string t){
                    	Datapool::getInstance()->setName(t);
                    };
            };
        public:
        	static Datapool *getInstance(){
            	static Datapool *dp = new Datapool();
            	return dp;
            };
            static klasseA *getKlasseA(){
            	static klasseA *a = new klasseA();
            	return a;
            };
            void setName(string n){
            	name = n;
            };
            string getName(){
            	return name;
            };
    };
    
    int main() {
    	Datapool *a = new Datapool();
    	Datapool *b = new Datapool();
    	Datapool *c = new Datapool();
    	a->getInstance()->getKlasseA()->setName("aa");
    	cout << Datapool::getInstance()->getKlasseA()->getName() << endl;
    	b->getInstance()->getKlasseA()->setName("bb");
    	cout << Datapool::getInstance()->getKlasseA()->getName() << endl;
    	c->getInstance()->getKlasseA()->setName("cc");
    	cout << Datapool::getInstance()->getKlasseA()->getName() << endl;
    
    	c->getKlasseA()->changeDatapoolName("lolo");
    	cout << Datapool::getInstance()->getName() << endl;
    	return 0;
    }
    

    oder evtl. so 😕

    #include <iostream>
    using namespace std;
    
    class Datapool{
    	private:
    		string name;
        public:
        	class klasseA{
                public:
                    static void changeDatapoolName(string t){
                    	Datapool::getInstance()->setName(t);
                    };
            };
        	static Datapool *getInstance(){
            	static Datapool *dp = new Datapool();
            	return dp;
            };
            string setName(string n){
            	return (name=n);
            };
            string getName(){
            	return name;
            };
    };
    
    int main() {
    	Datapool::klasseA::changeDatapoolName("lolo");
    	cout << Datapool::getInstance()->getName() << endl;
    	return 0;
    }
    

    lg lolo



  • datapool.h

    class KlasseA;
    
    class Datapool
    {
    public:
      KlasseA* getKlasseA() const { return klasseA; }
      //...
    private:
      KlasseA* klasseA;
    };
    

    datapool.cpp

    #include "klasseA.h"
    
    Datapool::Datapool()
    : klasseA(new KlasseA())
    {
      //...
    }
    
    //...
    

    so in etwa, wenn ich dich richtig verstanden habe



  • danke schonmal für die antwort Lolo

    bin nun nur mal theoretisch drüber gehüpft.

    Aber so wie ich das versteh legst du ja jedes mal nen neuen Datapool an, dass will ich ja durch das Singelton-Pattern verhindern.

    Ich will quasi einen Datapool der nur einmal existiert, auf den von jeder Klasse zugegriffen werden kann und über den man auf die Klasse KlasseA zugreifen kann.

    KlasseA soll einfach nachher ne MEthode ausführen können die z.b. zuerst einen wert aus dem Datapool ausliest , mit diesem Wert irgendwas berechnet und danach deb Wert wieder in Datapool schreiben könne.

    Des Weiteren soll z.b. KlasseA ne Funktion(z.b. Zeitmessen) besitzen , die wiederum von der main über den Datapool gestartet wird.

    Ich weiß hört sich kompliziert an 🙂



  • scheint so als müßtest du den contructor private setzen damit du keine neue instanz erstellen kannst die änderungen hab ich mal gepostet 😉

    class Datapool{
        private:
        	...
        	Datapool(){} //erzeugt ein singleton?
        	...
            class klasseA{
    
    int main() {
    	Datapool::getInstance()->getKlasseA()->setName("aa");
        cout << Datapool::getInstance()->getKlasseA()->getName() << endl;
        Datapool::getInstance()->getKlasseA()->setName("bb");
        cout << Datapool::getInstance()->getKlasseA()->getName() << endl;
        Datapool::getInstance()->getKlasseA()->setName("cc");
        cout << Datapool::getInstance()->getKlasseA()->getName() << endl;
    
        Datapool::getKlasseA()->changeDatapoolName("lolo");
        cout << Datapool::getInstance()->getName() << endl;
        cout << Datapool::getKlasseA()->getName() << endl;
        return 0;
    }
    


  • zwutz schrieb:

    datapool.h

    class KlasseA;
    
    class Datapool
    {
    public:
      KlasseA* getKlasseA() const { return klasseA; }
      //...
    private:
      KlasseA* klasseA;
    };
    

    datapool.cpp

    #include "klasseA.h"
    
    Datapool::Datapool()
    : klasseA(new KlasseA())
    {
      //...
    }
    
    //...
    

    so in etwa, wenn ich dich richtig verstanden habe

    was ich noch erwähnen sollte,

    die Klassen sollten getrennt sein. Also jede Klasse in eine cpp und header
    Tu mir da bisschen schwer so zusammengeschriebene Klassen auseinander zu bauen.
    Die einzelne Klassen werden spöter halt relativ groß, deswegen würd ichs gern auseinandr haben.



  • loe schrieb:

    die Klassen sollten getrennt sein.

    in meinem Beispiel sind sie getrennt

    dein datapool hält lediglich einen Zeiger auf KlasseA, der im Konstruktor des Datapools initialisiert wird



  • könnte man nicht auch direct die klasse mit nem #include rein laden 😕

    class Datapool{
        private:
        	Datapool(){}
            string name;
    		#include "klasseA.h"
        public:
    ...
    


  • zwutz schrieb:

    loe schrieb:

    die Klassen sollten getrennt sein.

    in meinem Beispiel sind sie getrennt

    dein datapool hält lediglich einen Zeiger auf KlasseA, der im Konstruktor des Datapools initialisiert wird

    könntest du mir bitte Zeile 1+6 aus der Datapool.h erklären

    und Zeile 1 in der Datapool.cpp müsste heissen Datapool.h und nicht KlasseA.h oder? die KlasseA.h muss in der Datapool.h eingebunden werden oder hab ich da grad nen totalen denkfehler?



  • noobLolo schrieb:

    könnte man nicht auch direct die klasse mit nem #include rein laden 😕

    class Datapool{
        private:
        	Datapool(){}
            string name;
    		#include "klasseA.h"
        public:
    ...
    

    nee
    #include kannst auch nur über der Klasse



  • loe schrieb:

    nee
    #include kannst auch nur über der Klasse

    sicher? das macht doch der preprocessor dem ist das doch gleich wo das steht, der hat doch keinen syntax check 🤡 ?



  • loe schrieb:

    könntest du mir bitte Zeile 1+6 aus der Datapool.h erklären

    Zeile 1 ist eine Forward Declaration. Sie macht KlasseA in datapool.h bekannt, ohne dass du den Header einbinden musst. Den bindest du erst in datapool.cpp ein, was die Abhängigkeiten der Klassen etwas verringert.
    Zeile 6 ist nur eine Methode, mit der man von außen lesend auf das KlasseA-Objekt zugreifen kann. Soll man über die Methode auch schreiben können, musst du das const weglassen

    loe schrieb:

    und Zeile 1 in der Datapool.cpp müsste heissen Datapool.h und nicht KlasseA.h oder? die KlasseA.h muss in der Datapool.h eingebunden werden oder hab ich da grad nen totalen denkfehler?

    datapool.h musst du natürlich auch einbinden. Ich habs nur weggelassen, da du es eh schon drinstehen hast.
    klasseA.h musst du aber einbinden, da du in der datapool.h ja lediglich eine Forward Declaration hast



  • Das scheint mir alles komplizierter zu sein als es eigentlich sein muss. Warum legst du alle Objekte dynamisch an bzw. arbeitest mit Zeigern wenn Referenzen genausogut funktionieren?
    Nächste Frage: Warum hat Klasse A eine Methode, die ein Element von DataPool ändert?

    Du brauchst im Header der KlasseA DataPool.h nicht zu inkludieren, da im Header keinerlei Informationen über DataPool bekannt sein müssen, weder Klassenlayout noch Methodensignaturen. Verschieb´ die Zeile in KlasseA.cpp.
    Vereinfacht kann das dann so aussehen:

    #ifndef KlasseAH
    #define KlasseAH
    
    #include <string>
    
    class KlasseA
    {
    public:
       void change_datapool_name( const std::string& Name );
    };
    #endif
    
    #include "KlasseA.h"
    #include "DataPool.h"
    
    using namespace std;
    
    /* Warum der Umweg über KlasseA? */
    void KlasseA::change_datapool_name( const string& Name )
    {
       DataPool::instance().set_name( Name );
    }
    
    #ifndef DataPoolH
    #define DataPoolH
    
    #include "string>
    
    #include "KlasseA.h"
    
    class DataPool
    {
       std::string Name_;
       KlasseA KlasseA_;
    
    public:
       DataPool& instance();
    
       KlasseA& KlasseA();
    
       std::string name() const;
       void set_name( const std::string& Name );
    
    private:
       DataPool();
       DataPool( const DataPool& );
       DataPool& operator=( const DataPool& );
    };
    #endif
    
    #include "DataPool.h"
    
    using namespace std;
    
    DataPool::DataPool()
    {
    }
    
    DataPool& DataPool::instance()
    {
       static DataPool theDataPool;
       return theDataPool;
    }
    
    KlasseA& DataPool::KlasseA()
    {
       return KlasseA_;
    }
    
    string DataPool::name() const
    {
       return Name_;
    }
    
    void DataPool::set_name( const string& Name )
    {
       Name_ = Name;
    }
    


  • Vielen Dank für eure Hilfen
    habs aber nun doch über Pointer gelöst und zwar so:

    /*  * Datapool.h * */
    #ifndef DATAPOOL_H_
    #define DATAPOOL_H_
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    
    #include "KlasseA.h"
    
    using namespace std;
    
    class Datapool{
    
    	private:
    		static Datapool* datapool;
    		KlasseA* meinPointer;
    
    	protected:
    		string name;
    		Datapool();
    
    	public:
    		static Datapool* getDatapool();
    		void setName(string n);
    		string getName();
    		KlasseA* getKlasseA();
    		void setKlasseA(KlasseA* pointer);
    };
    
    #endif /* DATAPOOL_H_ */
    
    // Datapool.cpp
    #include "Datapool.h"
    
    Datapool* Datapool::datapool = 0;
    
    Datapool::Datapool(){
    	name="";
    	meinPointer= NULL;
    }
    
    Datapool* Datapool::getDatapool(){
    	if (datapool == 0) {
    		datapool = new Datapool;
    	}
    	return datapool;
    }
    
    void Datapool::setName(string n){
    	name = n;
    }
    
    string Datapool::getName(){
    	return name;
    }
    
    KlasseA* Datapool::getKlasseA(){
    	if (meinPointer == NULL) {
    		meinPointer = new KlasseA();
    	}
    	return meinPointer;
    }
    
    void Datapool::setKlasseA(KlasseA* pointer){
    	meinPointer = pointer;
    }
    
    /*  * KlasseA.h *  */
    
    #ifndef KLASSEA_H_
    #define KLASSEA_H_
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    class KlasseA{
    
    	public:
    		KlasseA();
    		void changeDatapoolName(string n);
    };
    
    #endif /* KLASSEA_H_ */
    
    //KlasseA.cpp
    #include "KlasseA.h"
    #include "Datapool.h"
    
    KlasseA::KlasseA(){
    }
    
    void KlasseA::changeDatapoolName(string n){
    	Datapool::getDatapool()->setName(n);
    }
    
    //main.cpp
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string>
    #include "Datapool.h"
    
    using namespace std;
    
    int main(int argc, char *argv[]) {
      cout << "Singelton" << endl;
      Datapool::getDatapool()->setName("test1");
      cout << Datapool::getDatapool()->getName() << endl;
      Datapool::getDatapool()->getKlasseA()->changeDatapoolName("geaendert über KlasseA");
      cout << Datapool::getDatapool()->getName() << endl;
      return   0 ;
    }
    

Anmelden zum Antworten