[Anfänger] Frage zu Objekten in Klassen



  • Hallo Leute, ich bin noch recht frisch in der OOP und hab da mal eine Frage.
    Es geht um folgendes Problem.
    Ich habe eine Klasse geschrieben die mir auf einem RaspberryPi ein wenig die Arbeit erleichtern soll und die anprache der Hardware Schnittstelle übernimmt, und die evtl. Fehler darstellt.

    Nun wollte ich eine zweite Klasse bauen die ein Objekt der ersten erstellt, leider scheint es so wie ich es mir denke nicht möglichzu sein. Villeicht weiß einer von euch rat.

    Hier die erste Klasse

     class I2C
    {
        public:
            I2C(int Adress)
            { m_adress=Adress;};
    
            ~I2C();
    
            voidstartI2C ();
            void readI2C(int Register,bool width, int &Data);
            void writeI2C(int Register, bool width, int Data);
    
    }; 
    

    Hier die zweite und wie ich mir das denke:

    #include "I2C.h"
    class Digital_I_O
    {
        public:
            Digital_I_O();
            ~Digital_I_O();
            int Read_Port();
            bool Read_Pin(int pin);
            void Write_Port(int Data);
            void Write_Pin(int pin, bool status);
    
        private:
       I2C MCP23017(0x20); // Dies wird nicht akzeptiert würde aber gerne das Objekt für die Zugriffe nutzen.
    };
    

    villeicht kann mir einer von euch helfen? Wäre sehr dankbar.
    Gruß
    Gismo



  • @lord_gismo sagte in [Anfänger] Frage zu Objekten in Klassen:

    I2C(int Adress)
    { m_adress=Adress;};
    

    Benutze Initialisierungslisten:

    I2C(int Adress)
    :m_adress{ Adress }
    {}
    

    @lord_gismo sagte in [Anfänger] Frage zu Objekten in Klassen:

    ~I2C();
    

    Wozu ein wahrscheinlich leerer Destruktor?

    @lord_gismo sagte in [Anfänger] Frage zu Objekten in Klassen:

    I2C MCP23017(0x20);
    

    Schreibst Du

    I2C MCP23017{ 0x20 };
    

    oder

    I2C MCP23017 = 0x20;
    

    oder nutze die Initialisierungsliste.



  • Hallo Swordfish,
    vielen dank für die schnelle Antwort. Das mit der Initalisirungsliste kannte ich noch nicht. Danke für den Tip hat super funktioniert.
    Der Destructor wurde mit begebracht muss da sein damit dieser beim Beenden des Programmes aufgerufen wird und so sicher ist das , dass Objekt gelöscht wird. Begründung man kann sich nicht darauf verlassen dass, das OS diese Aufgabe übernimmt.
    Gruß
    Kristian



  • @lord_gismo sagte in [Anfänger] Frage zu Objekten in Klassen:

    Der Destructor wurde mit begebracht muss da sein damit dieser beim Beenden des Programmes aufgerufen wird und so sicher ist das , dass Objekt gelöscht wird. Begründung man kann sich nicht darauf verlassen dass, das OS diese Aufgabe übernimmt.

    Das ist schlicht völlig falsch. Sollte dir das jemand wirklich so gesagt haben, dann hat er keine Ahnung.



  • @lord_gismo sagte in [Anfänger] Frage zu Objekten in Klassen:

    Der Destructor wurde mit begebracht muss da sein damit dieser beim Beenden des Programmes aufgerufen wird und so sicher ist das, dass Objekt gelöscht wird. Begründung man kann sich nicht darauf verlassen dass, das OS diese Aufgabe übernimmt.

    Ein Destruktor, der nichts tut hat den gleichen Effekt als wäre er nicht da. Destruktoren werden auch nicht "beim Beenden des Programmes" aufgerufen, sondern immer dann, wenn ein Objekt out-of-scope geht:

    void foo()
    {
        bar_t bar;
    
        {
            baz_t baz;
            // sonstwas ...
        } // baz wird zerstört.
    
        // sonstwas ...
    
    } // bar wird zerstört.
    

    Anders ist das nur, wenn ein Objekt nicht im automatischen Speicher (meist Stack) sondern im Freispeicher (free-store, meist Heap) lebt. Dann wird das Objekt zerstört (und der Destruktor aufgerufen), wenn delete auf einen darauf verweisenden Pointer aufgerufen wird. In modernem C++ sollten jedoch new und delete nicht mehr in Anwendungscode auftauchen - man Verwendet Smart Pointer, die ihre Ressource, also den dynamischen Speicher und das Objekt darin, verwalten. Siehe RAII.



  • Hmm, interessant hatte mir schon gedacht das, dass Quatsch ist. Aber okay wozu ist der Destruktor dann nutzbar? Also was sollte darin stehen einfaches Feedback das, dass Entsprechende Objekt nicht mehr da ist bzw. unerwartet zerstört wurde ?



  • Die Aufgabe des Destruktors ist, alle Resourcen, die dieses Objekt besitzt freizugeben, falls dies nicht automatisch geschieht.

    Resourcen, die nicht automatisch freigegeben werden, können dabei alles mögliche sein; mit new/new[] angefordertes Memory, Handles auf Betriebssystemobjekte ...

    Aber wie von den Vorrednern angetönt, ist das dank RAII nur sehr selten notwendig. Eigentlich nur beim Bau von RAII-Containern.



  • @lord_gismo sagte in [Anfänger] Frage zu Objekten in Klassen:

    einfaches Feedback das, dass Entsprechende Objekt nicht mehr da ist bzw. unerwartet zerstört wurde ?

    "Feedback"? Wie könnte etwas "unerwartet zerstört werden"?

    Destruktoren sind dazu da, während der Lebenszeit eines Objekts belegte Ressourcen (Speicher, File-Handles, Mutexe, ...) wieder freizugeben. Informiere Dich bitte über RAII.



  • @lord_gismo sagte in [Anfänger] Frage zu Objekten in Klassen:

    Also was sollte darin stehen einfaches Feedback das, dass Entsprechende Objekt nicht mehr da ist bzw. unerwartet zerstört wurde ?

    Warum sollte das Objekt nicht mehr da sein bzw. unerwartet zerstört worden sein?

    Aber okay wozu ist der Destruktor dann nutzbar?

    Besorge dir ein anständiges Buch. Leider scheinen die Links zu den Bücherfragen hier im Forum nicht mehr zu funktionieren.



  • Wenn dein Object Ressourcen besitzt, die freigegeben werden müssen, dann solltest du dies im Destruktor tun. Beachte aber, dass du kann die Regel der 3 bzw. 5 (siehe https://en.cppreference.com/w/cpp/language/rule_of_three) einhalten musst. Daher solltest du in deinen Klassen möglichst nicht selbst Ressourcen verwalten. Und wenn du das doch machen musst, trenne die Ressourcen-Verwaltung von der normalen Funktionalität, indem du eine Klasse nur zur Ressourcenverwaltung erzeugst.

    Einen weiteren Fall gibt es, wo du einen Destruktor brauchst: wenn du mit Polymorphie arbeitest und deine Objekte als Pointer auf die Basisklasse nutzt, dann benötigst du einen virtuellen Destruktor. Dann schreibt man am besten virtual ~Foo = default;. Wenn du Polymorphie aber nicht nutzt, dann brauchst du den Destruktor auch nicht. Die "Rule of zero" sorgt für angenehme Klassen, die keine Überraschungen bieten.



  • Super vielen Dank für die ganzen Erklärungen. Ich hab mir heute ein Buch zum Thema bestellt. Aber ihr habt mir sehr weiter geholfen.
    Gruß Gismo



  • @wob sagte in [Anfänger] Frage zu Objekten in Klassen:

    Einen weiteren Fall gibt es, wo du einen Destruktor brauchst: wenn du mit Polymorphie arbeitest und deine Objekte als Pointer auf die Basisklasse nutzt löschen möchtest, dann benötigst du einen virtuellen Destruktor.

    Sonst reicht auch ein protected non-virtual Destruktor!