Große Verständnisprobleme beim ersten größeren C++-Projekt



  • Hallo Werner und alle anderen.

    Na dann probiere ich dir mal auf deine Frage zu antworten, damit du mir meine Frage beantworten kannst 🙂

    - wie ist der Roboter aufgebaut?
    Also: Der Roboter hat gewisse Komponenten, die sowohl Hardware (z.B. Greifarm) als auch Software (Selbstlokalisation und Pfadplanung) sein können.

    Innerhalb der Verwaltungsklasse sollen alle Komponenten zusammenlaufen (auch wenn das nicht von allen als gute Idee angesehen wird).
    Dadurch möchte ich in der Lage sein von der Verwaltungsklasse auf ALLE Methoden des gesamten Programms zugreifen zu können.

    - was soll er genau tun; was bedeutet 'autonom agieren'?
    Autonom agieren bedeutet, dass der Roboter in der Lage ist ein Problem nicht immer auf die gleiche Art und Weise zu erledigen, sondern auch Abweichungen vom "Plan" verkraften zu können. So sollen z.B. dynamische Hindernisse auf dem Pfad nicht zum Absturz des Programms, sondern zur Neuplanung des Pfades führen.

    - wie ist sein Input (Konfiguration, Sensoren, Aufgaben)?
    Sowohl Konfigurationsdateien als auch Sonarsensordaten, aber auch eine Sprachsteuerung, die Befehle in einer txt-Datei ablegt, die anschließend ausgeführt werden sollen.

    - wie ist sein Output (Arm-Motoren, fährt/geht er)?
    Das Abfahren (er fährt) der berechneten Pfade, sowie das Aufnehmen und Transportieren von Gegenständen (alles in einzelnen Klassen realisiert).

    - wie sieht ein typischer Anwendungsfall aus?
    Der Roboter bekommt den Befehl einen Gegenstand von A nach B zu transportieren.
    Bedeutet im Ablauf des Programms:
    - Verstehen des Befehls per Spracherkennung
    - Abspeichern des verstandenen Befehls in einer txt-Datei
    - Auslesen der Befehle aus der txt-Datei (der Umweg über die txt-Datei ist bewusst gewählt)
    - Pfadplanung zu Ort A
    - Abfahren des Pfades zu Ort A
    - Erkennen des Gegenstandes an Ort A
    - Aufnehmen des Gegenstandes
    - Pfadplanung zu Ort B
    - Abfahren des Pfades zu Ort B
    - Abladen des Gegenstandes

    Wie ihr sehen könnt, da ist einiges zu tun, wobei das nur ein Teil meiner Zielapplikation ist, aber schon ein wichtiger!!

    Danke für jede Hilfe 👍 👍



  • oha 😮
    bastelst du an dem ding alleine just for fun im hobbykeller rum? oder gibt es evtl irgendein "team" oder eine arbeitsgruppe oder sowas? falls ja: wie siehts denn mit den anderen aus, wärs evtl besser, sich mit den abzusprechen?



  • Nee, ich arbeite da alleine dran. Lediglich die Spracherkennung wird von jemand anderem übernommen. Aber ich muss auch nicht alles von Grund auf implementieren. Es gibt eine API, die z.B. die Pfadplanung übernimmt und ich muss diese nur noch anstoßen.
    Also fange ich nicht ganz bei Null an, aber es bleibt noch genug Arbeit übrig 🙄



  • Das mit der Verwaltungklasse ist also vorgegeben, ja?
    Auf jeden Fall solltest du dir die anderen Entfwurfsmuster auf der Seite, die ich genannt habe, auch nochmal angucken. Das wird dir sicherlich helfen. Alternativ könnte ich dir die Investition in "Head First Design Patters/Entwurfsmuster von Kopf bis Fuß" empfehlen. Ist aber nicht ganz billig das Ding, ich habs mir von einem Gutschein gekauft :p



  • Dr.Ottel schrieb:

    Na dann probiere ich dir mal auf deine Frage zu antworten, damit du mir meine Frage beantworten kannst 🙂

    Na - dann will ich's mal probieren.

    Im Prinzip ist doch das eine Art Transporter. In der realen Welt gibt es da u.a. Schubkarren, LKws und Schiffe. Da beim Software Design die Kunst im Teilen und Herrschen besteht, nehme ich ein Vorbild, wo schon viel Aufgaben verteilt sind; wie auf einem Schiff.

    Mal angenommen es gibt einen Kapitän. Der hat einen Greifer (Lademeister), einen Navigator und eine externen Kommandeur. Vom Kommandeur werden die groben Anweisungen gemeldet "Fahre nach A hole Paket P1 bringe nach B". Der Kapitän zerlegt die Anweisungen in kleinere Happen an Navigator und Greifer. An den Navigator "fahre nach A". Der Navigator seinerseits besitzt eine Karte und einen Steuermann. Der Navigator führt an Hand der Karte eine Pfadplanung durch und gibt dem Steuermann einzelne Fahrbefehle: Steuermann drehe um 120Grad volle Kraft voraus fahre 13,5m. Der Steuermann hat einen oder hat Zugriff auf Antrieb und Lenkung und tut was ihm geheißen. Wenn er die Strecke zurückgelegt hat meldet er das 'nach oben'. Der Navigator gibt ihm dann den nächsten Fahrbefehl und wenn der Steuermann fertig beim letzten meldet, so meldet der Navigator "Ziel erreicht" an den Kapitän. Der beauftragt seinen Greifer das Paket P1 zu fassen. Der Greifer wiederum hat einen oder hat Zugriff auf den Roboterarm und tut wie ihm geheißen {hier braucht man noch mehr Input}. Der Greifer meldet ok 'nach oben' und der Kapitän beauftragt wieder den Navigator usw.

    Der Navigator hat eine Möglichkeit seine Position_und_Richtung im Raum zu bestimmen {wie kann der Roboter das? wie funktioniert die Selbstlokalisation - bzw. was ist ihr Output?} so kontrolliert er den Weg des Steuermanns. Der Steuermann hat noch ein Sonar mit dem er Hindernisse nach vorne erkennt. Trifft der Roboter während der Fahrt auf ein Hindernis, so hält er an und meldet das 'nach oben'. Der Navigator trägt das Hindernis in seine Karte ein und beauftragt mit den neuen Informationen die Pfadplanung. Mit dem neuen Pfad gibt er wieder Anweisungen an den Steuermann.

    So - alle fett gedruckten Hauptwörter sind Klassen. Jedesmal wenn ein 'hat' erscheint ist das eine Aggregation. Also bei A hat B ist B ein Member von A; entweder direkt oder über Pointer und Interface-Klasse wie von viande schon beschrieben. Ein 'hat Zugriff auf' kann ein Zugriff auf eine Ressource sein, die von einem externen (?) System instantiiert wird. Also Sonar, Antrieb, Lenkung und Roboterarm sind sicher nur einmal vorhanden, könnten also auch ein Singleton sein.
    Jedes meldet bzw. meldet 'nach oben' ist ein Callback-Aufruf. Die Callback-Funktoren werden dem jeweiligen Server beim Anlegen gleich mitgegeben.
    Der Vorteil ist hier, dass die Serverklassen ihren jeweiligen Client gar nicht kennen müssen. Jede Klasse kennt nur wieder die Klassen an deren Objekte es Kommandos abgibt.

    Jetzt habe ich noch vergessen zu erwähnen, dass der externe Kommandeur eine Spracherkennung hat. Und die Pfadplanung ist eine Funktion; mit den Parametern Standort, Ziel und Karte und dem Returntyp Pfad (Polygon).

    Zur Strukturierung: Wahrscheinlich muss das ganze "Event getrieben" sein, um quasi ein asynchrones Verhalten hinzubekommen. Also z.B. muss ja eine Spracherkennung auch unter dem Fahren möglich sein und nicht erst wenn die komplette Aufgabe erledigt ist (ist das so?). D.h. jeder Methodenaufruf eines Clients an einen Server startet nur die Aktion, kommt aber unmittelbar zurück. Da die Fertigmeldungen immer über Callbacks laufen ist das auch kein Problem. Wenn man das ganze als Singlethread-Applikation auslegt (würde ich erstmal versuchen) so benötigt man eine Hauptschleife, in der auf alle externen Events (Sonar, Endschalter, Sprachsignal) gewartet wird. Und jedes Objekt welches ein Event benötigt muss sich dort mit einem Interface 'anmelden' (siehe Adapter Pattern)

    So weit so gut, jetzt ist Dr.Ottel wieder dran seine Meinung zu äußern. Die Bemerkungen in {} sind noch zu klären (s.o.). Insbesondere ist mir nicht klar, wie das Zugreifen passieren soll. Der Roboter muss doch dazu eine bestimmte Position zum Objekt haben und ggf. das Objekt auch "sehen" könne - oder wie funktioniert das?

    Ach so und warum

    Dr.Ottel schrieb:

    Dadurch möchte ich in der Lage sein von der Verwaltungsklasse auf ALLE Methoden des gesamten Programms zugreifen zu können.

    ist das so und welche Methoden sind hier genau gemeint?

    Und

    viande schrieb:

    Das mit der Verwaltungklasse ist also vorgegeben, ja?

    das hoffe ich doch nicht - wenn ja wieso?

    Gruß
    Werner



  • Erstmal großen Respekt für deine Schilderung, denn ich gehe mal davon aus, dass du nicht so viel Ahnung von Robotik hast und dafür ist das Ganze SEHR gut und genau erklärt.

    Dein Kommunikationskonzept klingt besser als das mit der zentralen Verwaltungsklasse, denn so kann ich auch Zugriffe über 2 Zeiger und sonstige abstrusen Konstrukte vermeiden.

    Zu deinen Fragen:
    Roboterarm:
    Der ist relativ simple konstruiert und kann sich nur öffnen/schließen und nachdem er z.B. ein Objekt gegriffen hat, sich nach oben bzw. unten bewegen.

    Selbstlokalisation:
    Der Roboter berechnet anhand der mitgegebenen Karte und den aktuellen Sonarreadings Wahrscheinlichkeiten dafür aus, wo er sich am wahrscheinlichsten befindet und gibt dafür auch die Wahrscheinlichkeit von 0 bis 1 aus.

    Sprachsteuerung:
    Darum kümmere ich mich gar nicht. Ich bekomme nur die Liste mit den Befehlen, die ich abarbeiten soll.

    Nochmals vielen Dank für die Antworten. Sie bringen mich echt weiter!!



  • Dr.Ottel schrieb:

    .. denn ich gehe mal davon aus, dass du nicht so viel Ahnung von Robotik hast

    Nun ich habe schon etwas mit Robotik zu tun; aber meine fahren nicht, können nicht hören und Sonar ist auch nicht.

    Dr.Ottel schrieb:

    Roboterarm:
    Der ist relativ simple konstruiert und kann sich nur öffnen/schließen und nachdem er z.B. ein Objekt gegriffen hat, sich nach oben bzw. unten bewegen.

    Ok - für den Greifer sieht das einfach aus. Natürlich muss die Position des Roboters stimmen, sonst greift's nicht.

    Dr.Ottel schrieb:

    Selbstlokalisation:
    Der Roboter berechnet anhand der mitgegebenen Karte und den aktuellen Sonarreadings Wahrscheinlichkeiten dafür aus, wo er sich am wahrscheinlichsten befindet und gibt dafür auch die Wahrscheinlichkeit von 0 bis 1 aus.

    Oh oh - das sieht schwierig aus. Naja Du weißt ja wo Du Fragen los werden kannst.

    Viel Erfolg
    Werner



  • Hi,
    ich finde es ziemlich interessant zu hören wie ihr euch hier Gedanken macht.

    Ich selbst beschäftige mich momentan auch mit Objektübergreifender Kommunication und bin deswegen sehr neugierig auf richtig gute Lösungsvorschläge. Ich arbeite momentan auch an einer kommunikationsplatform wenn man so will und bin mit der dort verwendeten Lösung überhaupt nicht einverstanden da die Erweiterung sowas von umständlich ist.

    Bei mir gibt es sowas wie eine Zentrale Verwaltungsklasse in der alle Kommunikationsvorgänge registriert werden müssen.

    Wenn ich jetzt im Übertragenen Sinn einen 6ten Finger an meine Hand implementieren möchte müsste ich praktisch im Gehirn bescheidgeben das der neue Finger bitte in der Lage sein soll mit ihm zu kommunizieren anstatt einfach der Hand mitzuteilen das sie jetzt einen neuen Finger hat und doch bitte dafür sorgen soll das er auch wunderbar funktioniere. Und da jeder Körperteil, Organ sowas wie einen Vorgesetzten hat soll die Information über den Neuen Finger sollange die Hirarchie hochwandern bis der OberSuperLeutnantGeneral mitbekommt das er jetzt nen neuen Sklaven hat. (Den interessiert es recht wenig da er ja schon weiss wie so ein Finger funktioniert, er freut sich nur über ein neues Feature.)

    Wenn wir uns das menschliche Gehirn mal (vereinfacht als Ganzes) denken dann fällt auf das es ansich nichts selbst kann, aber es kann was die Summe der andern Körperteile kann. Ich glaube das ist so deine Idee. Einen Punkt von wo aus man die "Kontrolle" hat.



  • Zur Strukturierung: Wahrscheinlich muss das ganze "Event getrieben" sein, um quasi ein asynchrones Verhalten hinzubekommen. Also z.B. muss ja eine Spracherkennung auch unter dem Fahren möglich sein und nicht erst wenn die komplette Aufgabe erledigt ist (ist das so?). D.h. jeder Methodenaufruf eines Clients an einen Server startet nur die Aktion, kommt aber unmittelbar zurück. Da die Fertigmeldungen immer über Callbacks laufen ist das auch kein Problem. Wenn man das ganze als Singlethread-Applikation auslegt ...

    jeder Methodenaufruf eines Clients an einen Server startet nur die Aktion, kommt aber unmittelbar zurück...das passiert ja auch wenn ich keine callbacks verwende?



  • Waldi1 schrieb:

    jeder Methodenaufruf eines Clients an einen Server startet nur die Aktion, kommt aber unmittelbar zurück...das passiert ja auch wenn ich keine callbacks verwende?

    Nein, nicht unbedingt. Ein sogenannter synchrone Aufruf käme erst zurück, wenn dass was er verursacht auch beendet wird.
    Zum Beispiel wenn der Kapitän den Navigator beauftragt die Position A anzufahren, so wäre es vordergründig am einfachsten zu programmieren, wenn dieser Aufruf erst zurückkommt, wenn der Roboter auch bei A angekommen ist. Der Navigator hängt somit seinerseits die meiste Zeit auf Aufrufen an den Steuermann. Beide - Kapitän und Navigator - können in dieser Zeit auf nichts reagieren (ich unterstelle eine Singlethread Applikation). Ein Stop-Ruf von außen - via Spracherkennung und externen Kommandeur müsste somit über den Steuermann (und/oder den Greifer) geleitet werden, um ggf. eine Fahrt zu unterbrechen. Das wiederum stellt die ganze Struktur auf den Kopf.

    GreyHound schrieb:

    Wenn wir uns das menschliche Gehirn mal (vereinfacht als Ganzes) denken dann fällt auf das es ansich nichts selbst kann, aber es kann was die Summe der andern Körperteile kann. Ich glaube das ist so deine Idee. Einen Punkt von wo aus man die "Kontrolle" hat.

    Die Frage ist immer auf welchen Level, bzw. mit welcher Granularität.

    Wenn ich das Modell Mensch auf den Roboter übertrage, so wird das Gehirn die Steuerung sein. Als Programmierer kann man das nicht 'als Ganzes' sehen, weil es ist ja gerade seine Aufgabe diese Steuerung zu bauen; und das geht ab einer gewissen Komplexität nur über eine gewisse Strukturiere (teile und herrsche Prinzip). Im oben beschriebenen Beispiel sind alle Klassen Teil des Gehirns, und erst Steuermann und Greifer steuern irgendwelche Motoren oder Stellelemente.

    GreyHound schrieb:

    Ich arbeite momentan auch an einer kommunikationsplatform wenn man so will und bin mit der dort verwendeten Lösung überhaupt nicht einverstanden da die Erweiterung sowas von umständlich ist. ...

    Wie stellst Du Dir denn selber eine verbesserte Software-Struktur in Deinem Fall vor? Oder anders gefragt: welche Eigenschaften soll eine verbesserte Software-Struktur haben?

    Gruß
    Werner



  • Werner Salomon schrieb:

    Wie stellst Du Dir denn selber eine verbesserte Software-Struktur in Deinem Fall vor? Oder anders gefragt: welche Eigenschaften soll eine verbesserte Software-Struktur haben?

    Super Frage, gut dass du sie stellst. Ist garnicht einfach darauf zu antworten, danke dafür schonmal. Nach ewigem überlegen bin ich Dir schonmal dankbar das du "in Deinem Fall" geschrieben hast. Ich glaub das war schon nen wichtiger Lernprozess.

    An der Antwort muss ich länger basteln, werd mich nun fürs erste ins Bett verkrümmeln.

    Was in meinem Fall wichtig wäre, wäre das Abtreten der Verantwortlichkeit über den Nachrichtenfluss an die jeweiligen Untergebenen sodass nicht am "Herz" des Programms gefrickelt werden muss um einer neuen Komponente mitzuteilen was schon alter Hut ist. In einem Satz könnte das vielleicht in der Art beschrieben sein: Implementation einer schon bekannten Funktionalität für eine neue Komponente sollte nicht die Modifikation der Steuerung benötigen.

    Ich hab um 12 angefangen zu replien, ich schicks jetzt einfach ab da ich eh nie zufrieden sein werde. 😡

    so lang geschrieben und dann das gute nacht vergessen, also dann im [edit]

    gut nacht 😉



  • Ich bin echt beeindruckt von der Eigendynamik, die dieser Thread entwickelt hat.

    Dennoch habe ich noch einige Fragen zu "alten Kamellen".

    Es geht um das Entwurfsmuster Singleton:
    In der Header-Datei habe ich folgendes stehen:
    static Abschlussarbeit* getInstance();

    diese Header-Datei inkludiere ich dann in der cpp-Datei und da habe ich dann folgendes stehen:

    Verwaltung* Verwaltung::getInstance()
    {
    static Verwaltung instance;
    return &instance;
    }

    Ist das so korrekt gelöst??

    Wenn ich jetzt in verschiedenen Klassen jeweils Verwaltung::getInstance() aufrufe bekomme ich dann immer dieselbe Instanz/Objekt?? Das ist ja der eigentliche Sinn der ganzen Geschichte...

    Dann noch eine Frage, die wahrscheinlich für die alten Hasen leicht zu beantworten sein wird, aber leider für mich nicht.

    In der Verwaltungsklasse muss ich ein privates Attribut hinterlegen, dass man am besten mit 3 Parametern initialisiert, bevor man es verwenden kann.
    Das kann ich aber schlecht machen, da ich in der Header-Datei nicht einfach so die Argumente angeben kann.
    Wie kann ich das Problem umgehen/lösen bzw. wie kann ich das private Attribut später richtig mit seinen Parametern initialisieren? Soll ich das erstmal mit dem Standardkonstruktor der Parameterklasse erzeugen und dann später im Konstruktor der Verwaltungsklasse richtig initialiseren? Wie am besten?

    Also, falls ich etwas verworren rede, was gerne mal vorkommt 😉
    Header der Verwaltungsklasse:
    private:
    KlasseEins klasse1; //Aufruf Standardkonstruktor, der vom System erstellt wird, weil in der API keiner angegeben ist?!

    Dann in der Verwaltungsklasse selber:
    Am besten wahrscheinlich im Konstruktor der Verwaltungsklasse das Objekt von KlasseEins neu anlegen, aber wie genau??

    Noch eine dumme Frage: wenn ich aus einer Klasse Verwaltung::getInstance() aufrufe und aus einer anderen Klasse dann nochmal, dann wird der Konstruktor der Verwaltungsklasse doch nur im ersten Fall aufgerufen, oder??

    Vielen Dank für die Hilfe!!



  • Es wäre echt schön, wenn mir jemand helfen könnte, da ich meine Arbeit bald abgeben muss 😮



  • Das Singleton müsste OK sein solange du nicht aus mehreren Threads "getInstance" aufrufst, und solange das "Verwaltung vs. Abschlussarbeit" ein Schlampigkeitsfehler in deinem Posting war.
    EDIT: "müsste" heisst: kommt drauf an wo du's verwendest. Guckst du da:

    http://www.parashift.com/c++-faq-lite/ctors.html ([10.14])

    /EDIT

    Das andere geht so (bloss ein unsinniges Beispiel um die Syntax zu zeigen):

    class foo
    {
    public:
        foo(int a, int b, int c)
            : m_a(a), m_b(b), m_c(c)
        {}
    
    private:
        int m_a;
        int m_b;
        int m_c;
    };
    
    class bar
    {
    public:
        bar(int x);
    
    private:
        const foo m_foo; // muss natürlich nicht const sein, kann aber
    };
    
    // in bar.cpp:
    
    static int compute_c(int x)
    {
       // ...
       return 123;
    }
    
    bar::bar(int x)
        : m_foo(x, 666, compute_c(x))
    {
    }
    

    Nennt sich "initializer-list".



  • Wow, vielen Dank!! Damit ist mir auf jeden Fall geholfen und ja es war ein Tippfehler...

    Noch eine Frage: Ich beschäftige mich schon länger mit der Informatik und der Programmierung und immer wieder taucht in Beispielen die Variable foo auf. Was ist denn die Geschichte dahinter??





  • static Abschlussarbeit* getInstance();
    
    Verwaltung* Verwaltung::getInstance() 
    {
    	static Verwaltung instance;
    	return &instance;
    }
    

    Ist das so korrekt gelöst??

    Jein.

    "static" in der KLassendeklaration meint Klassenmethode bzw Variable.
    "static" in einer Methode meint "Initialisierung genau beim ersten Durchlauf".

    Das Singletonmuster sieht in C++ eigentlich etwas anders aus:

    // Verwaltung.hpp
    class Verwaltung
    {
    
        public:
            static Verwaltung* getInstance();
        /*
         * ...
         */ 
        protected:
        // für Kindklassen; sonst auch privat !
            Verwaltung(); 
            virtual ~Verwaltung();    
        /*
         * ...
         */ 
        private:
            static Verwaltung* _pInstance;  
        /*
         * ...
         */ 
    
    };
    // EOF Verwaltung.hpp
    
    // Verwaltung.cpp
    #include "Verwaltung.hpp"
    
    Verwaltung* Verwaltung::_pInstance = (Verwaltung*)NULL; // Wichtig; sonst linkt es nicht  
    
    Verwaltung* getInstance()
    {
        if ( NULL == _pInstance )
        {
            _pInstance = new Verwaltung();
        } 
        return _pInstance;
    
    };
    
    Verwaltung(){}; 
    ~Verwaltung(){};
    
    // EOF Verwaltung.cpp
    

    So wird _pInstance in einem bestimmten Speicherbereich (meist "Heap" genannt) angelegt. Und kann auch von einem "friend" ( bei private ) oder auch einer Kindklasse ( bei protected ) ggf zum Programmende wieder zu einem definierten Zeitpunkt destruiert werden - aber von niemand anderem wg. des protected oder private.

    Wo eine lokaler "static" Variable liegt wissen Götter und Compiler-Entwickler.
    Sowas kann Probleme machen!
    Wann ( und ggf sogar ob - da bin ich mir nicht sicher obs im Standard garantiert wird ) die Variable auch wieder destruiert wird laesst sich kaum steuern.

    Wenn ich jetzt in verschiedenen Klassen jeweils Verwaltung::getInstance() aufrufe bekomme ich dann immer dieselbe Instanz/Objekt?? Das ist ja der eigentliche Sinn der ganzen Geschichte...

    Jein.

    Innerhalb einer Instanz des Codes ja - also innerhalb eines Programms oder eines statisch gelinkten Bibliothek.
    Bei einer DLL sieht das _GANZ_ aus. Da müsste getInstance() mehr leisten.

    Dann tritt insgesamt noch die Frage auf ob Das Programm mehrere Threads unterscheidet.

    Dann müssen _ALLE_ Funktionen mit Zugriff auf ein gemeinsames Objekt mittels Mutex / Semaphore / Critical / Section / Event geschützt werden, wenn aus auch eine schreibende Funktion gibt.
    Also nicht Zugriff auf "normale" automatische lokale Variablen,

    void foo() 
    {
        int i; // also sowas  
    }
    

    wohl aber KLassen- und Instanzvariablen und statische Variablen in Funktionen...

    Gint es Nebenläufigkeit (aka. "Multithreading") in dem Projekt ?

    Grüsse

    Gast++



  • Streiche:

    Verwaltung* getInstance()
    {
        if ( NULL == _pInstance )
        {
            _pInstance = new Verwaltung();
        } 
        return _pInstance;
    
    };
    
    Verwaltung(){}; 
    ~Verwaltung(){};
    

    Setze:

    Verwaltung* Verwaltung::getInstance()
    {
        if ( NULL == _pInstance )
        {
            _pInstance = new Verwaltung();
        } 
        return _pInstance;
    
    };
    
    Verwaltung::Verwaltung(){}; 
    Verwaltung::~Verwaltung(){};
    

    Vielleicht sollte ich doch besser in ner IDE schreiben...
    😉



  • Danke für die ausführliche Antwort!!

    Mmh, leider gibt es Multithreading in meinem Projekt...
    Ich hab gelesen, dass ich auch noch den Kopierkonstruktor der Verwaltung beim Entwurfsmuster Singleton vor einem öffentlichen Zugriff schützen muss. Das wurde bislang nicht erwähnt. Soll es trotzdem gemacht werden?

    Danke für deine Hinweise. Das werde ich direkt heute abend mal durchdenken und ausprobieren...



  • Dr.Ottel schrieb:

    Ich hab gelesen, dass ich auch noch den Kopierkonstruktor der Verwaltung beim Entwurfsmuster Singleton vor einem öffentlichen Zugriff schützen muss.

    Ups, jetzt hast Du mich aber erwischt!

    Ich sollte _wirklich_ lieber echtes Beispiel in den Editor laden und kopieren...

    Dr.Ottel schrieb:

    Das wurde bislang nicht erwähnt. Soll es trotzdem gemacht werden?

    Ja, unbedingt!
    Und gleich auch noch den Zuweisungsoperator.
    Beide private deklarieren.

    Dr.Ottel schrieb:

    Danke für deine Hinweise. Das werde ich direkt heute abend mal durchdenken und ausprobieren...

    Dr.Ottel schrieb:

    Danke für die ausführliche Antwort!!
    Mmh, leider gibt es Multithreading in meinem Projekt...

    Dann hast Du unter C++ aber _wirklich_ eine Aufgabe vor Dir!

    1. Gefährdete Variablen sollten nie nach aussen gereicht werden, also nie einen Pointer oder eine Referenz auf ein Member zurückgeben.

    2. Klassen- und Instanzvariablen sind eh nie public. Punkt.

    3. "static" in Funktionen ist ekelhaft. Bin bislang immer ( 10 Jahre lang ) gut ohne das ausgekommen.

    4. 5 Philosphen sitzen an einem runden Tisch beim chinesischen Abendessen. Zwischen Tellern in dem Rund liegt jeweils genau ein Chop-Stick.
      Jeder braucht zwei Chop-Sticks zum Essen.
      Jeder greift zum Stick zu seiner Rechten und wartet auf den Linken.
      => Alle bleiben hungrig !

    Das nennt man einen "Deadlock" - zwei Threads haben jeweils ein notwendiges Synchronisationsobjekt (SO, also Mutes et al.) locked und warten jeweils gegenseitig darauf dass der jeweils andere das jeweils andere Synchronisationsobjekt freigibt.

    So bewegt sich nichts mehr!

    => Möglichst nie einen zweiten exklusiven Zugriff für einen Ablauf anfordern.
    Das erste zunächst wieder freigeben.

    1. "Wenn zwei sich streiten freut sich der Dritte": oder
      "Kann man eine Konkurrenz nicht dialogisch klären, braucht es einen Moderator"

    Das gilt für (C++)Klassen und Threads genauso.

    1. Queues und asynchrone ("You called me? - call later or I'll call you back!") Schnittstellen sind hilfreich.

    2. Die STL ist nicht threadsicher.

    Viel mehr als dies und ein Buch "Pham/Garg : Multithreaded Programming with Win32" hatte ich auch nicht bei meinem ersten nebenläufigen Systemkonzept.

    Good Luck

    *this


Anmelden zum Antworten