Beinhaltet List-Container Objekte oder Referenzen?



  • Da habe ich mich soch tatsächlich verschrieben. Ich meine natürlich, dass die Zuweisungs-Funktions beim Einfügen der Objekte in die Liste nicht aufgerufen werden. Einen Kopier-Konstruktor habe ich gar nicht implementiert. Liegt da das Problem?



  • Ja.
    Übrigens, es heißt Destruktor und nicht Dekonstruktor. 🙂



  • Gustav Hummel schrieb:

    ...Einen Kopier-Konstruktor habe ich gar nicht implementiert. ...

    <=>

    Gustav Hummel schrieb:

    ...
    Nun habe ich bei jedem ... Copykonstruktor entsprechend eine Ausgabezeile eingefügt per cout....

    😕

    Wenn ein "flache Kopie" nicht GENAU das ist, was Du willst, reicht der implizit erzeugte CopyCtor nicht aus (und die Ausgabe einer Textzeile übernimmt der auch nicht für Dich). Da Du anscheinend mit dynamischem Speicher arbeitest, sieht es sehr danach aus, als ob das Dein Problem sei.

    Gruß,

    Simon2.



  • Ok Danke. hab mich gleich dran gemacht die Copy-Konstruktoren zu implementieren. Bin aber auf folgendes gestoßen:

    MyClass::MyClass(const MyClass &newObject)
    {
     m_myTestInt = newObject.m_myTestInt;
     m_myOtherObject = newObject.m_myOtherObject;  // <- bringt Fehlermeldung
    }
    MyClass &MyClass::operator=(MyClass &newObject)
    {
     if(this != &newObject) 
     {
      m_myTestInt = newObject.m_myTestInt;
      m_myOtherObject = newObject.m_myOtherObject;  // <- bringt Fehlermeldung
     } 
     return *this;
    }
    

    Fehlermeldung:

    error: no match for ‘operator=’ in ...

    Doch in der Zuweisungsmethode funktioniert genau das ohne Fehlermeldung des Compilers. m_myOtherObject besitzt einen selbst implementierten = Operator (getestet und geht auch). Muss ich im Copy-Konstruktor etwas spezielles beachten?

    Gruß
    Gustav



  • Korrektur:

    MyClass::MyClass(const MyClass &newObject)
    {
     m_myTestInt = newObject.m_myTestInt;
     m_myOtherObject = newObject.m_myOtherObject;  // <- bringt Fehlermeldung
    }
    MyClass &MyClass::operator=(MyClass &newObject)
    {
     if(this != &newObject)
     {
      m_myTestInt = newObject.m_myTestInt;
      m_myOtherObject = newObject.m_myOtherObject;  // <- bringt !!keine!! Fehlermeldung
     }
     return *this;
    }
    


  • welchen Typ hat denn m_myOtherObject ?

    Gustav Hummel schrieb:

    ...m_myOtherObject besitzt einen selbst implementierten = Operator ...

    Glaub' ich nicht ! 😉
    Wenn, dann hat die Klasse einen operator=() ...

    Hast Du vielleicht mit einer forward-deklaration gearbeitet ?
    hmmm ...

    Gruß,

    Simon2.



  • Schreib doch mal die ganze Fehlermeldung hin.



  • Simon2 schrieb:

    welchen Typ hat denn m_myOtherObject ?

    Gruß,

    Simon2.

    Hallo,
    genau ich arbeite mit dynamischen Speicher... m_myOtherObject ist vom eigenen Typ MyDynamicClass. Und genau hier nutze ich dynamisches Speicher. In der Klasse MyDynamicClass sind nun Konstruktor, Destruktor, Copy-Konstruktor und Zuweisungsoperator vorhanden bzw. selbst implementiert.



  • Braunstein schrieb:

    Schreib doch mal die ganze Fehlermeldung hin.

    Komplette Fehlermeldung:

    Severity and Description Path Resource Location Creation Time Id
    error: no match for ‘operator=’ in ‘((MyClass*)this)->MyClass::m_myOtherObject = newMyClass->MyClass::m_myOtherObject’ TestProjekt myClass.cpp line 46 1182246184643 2815



  • Hilfreich wäre auch die Fehlermeldung. Aber ich rate mal: Es liegt am const. Dein op= nimm (warum auch immer keine const-Referenz), wenn das beim anderen op= genauso ist, dann kann er im Copy-Konstruktor (der ja ne const-referenz nimmt) nicht verwendet werden.



  • Hallo Jester,

    die Fehlermeldung findest du in meinem letzten Beitrag. Vielleicht hilft es, wenn ich noch Copy-Konstruktor und Zuweisungsfunktion der myDynamicClass Klasse poste:

    MyDynamicClass &MyDynamicClass::operator=(MyDynamicClass &newMyDynamicClass)
    {
       cout << "Zuweisung MyDynamicClass" << endl << flush;
    
       // is new object the same object?
       if(this != &newMyDynamicClass)
       {
          // free memory
          if(m_puiData != NULL)
          {
             delete [] m_puiData;
          }
    
          // copy data
          m_uiStartAddress = newMyDynamicClass.m_uiStartAddress;
          m_uiLength = newMyDynamicClass.m_uiLength;
    
          m_puiData = new uint16_t[m_uiLength];
    
       	for(uint16_t uiDummy = 0; uiDummy < m_uiLength; ++uiDummy)
       	{
       		m_puiData[uiDummy] = newMyDynamicClass.m_puiData[uiDummy];
       	}          
       }
    
       return *this;
    }
    
    MyDynamicClass::MyDynamicClass(const MyDynamicClass &newMyDynamicClass)
    {
    	// copy data
    	m_uiStartAddress = newMyDynamicClass.m_uiStartAddress;
    	m_uiLength = newMyDynamicClass.m_uiLength;
    
    	m_puiData = new uint16_t[m_uiLength];
    
    	for(uint16_t uiDummy = 0; uiDummy < m_uiLength; ++uiDummy)
    	{
    		m_puiData[uiDummy] = newMyDynamicClass.m_puiData[uiDummy];
    	} 	
    }
    


  • Ich würde dir raten, den Zuweisungsoperator über den CopyCtor zu implementieren (spart Schreibarbeit, nutze swap) und bei beiden den Parameter als const Referenz zu übernehmen.
    Das flush nach dem endl ist auch zuviel. endl mach schon selbst ein flush.



  • Danke für die Tipps. Funktioniert jetzt auch.

    Meintest du so?:

    MyDynamicClass &MyDynamicClass::operator=(const MyDynamicClass &newMyDynamicClass)
    {
       cout << "Zuweisung MyDynamicClass" << endl;
    
       // is new object the same object?
       if(this != &newMyDynamicClass)
       {
          // free memory
          if(m_puiData != NULL)
          {
             delete [] m_puiData;
          }
    
          // copy data
          MyDynamicClass(newMyDynamicClass);       
       }
    
       return *this;
    }
    

    Gruß
    Gustav



  • Nein, das funktioniert nicht. Da wo Du vermeintlich den Copy-Konstruktor verwendest erstellst Du nur ein temporäres Objekt. Gemeint war:

    MyDynamicClass const& operator=(MyDynamicClass const& other)
    {
      MyDynamicClass tmp(other);
      tmp.swap(*this);
      return *this;
    }
    


  • EDIT: jetzt überflüssig.



  • Jester schrieb:

    Nein, das funktioniert nicht. Da wo Du vermeintlich den Copy-Konstruktor verwendest erstellst Du nur ein temporäres Objekt. Gemeint war:

    MyDynamicClass const& operator=(MyDynamicClass const& other)
    {
      MyDynamicClass tmp(other);
      tmp.swap(*this);
      return *this;
    }
    

    ich müsste also lediglich eine swap funktion implementieren mit folgendem code:

    std::swap(m_uiStartAddress, src.m_uiStartAddress);
    	std::swap(m_puiData, src.m_puiData);
    	std::swap(m_uiLength, src.m_uiLength)
    

    (also alle Elemente tauschen)

    Seh ich richtig, dass somit beim = Operator kein delete mehr nötig ist, da die 2 Objekte getauscht werden und somit das ursprüngliche Objekt(this) zum temporären wird und dieses per Destruktor freigegeben wird?

    Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?

    Gruß
    Gustav



  • Gustav Hummel schrieb:

    ich müsste also lediglich eine swap funktion implementieren mit folgendem code:

    std::swap(m_uiStartAddress, src.m_uiStartAddress);
    	std::swap(m_puiData, src.m_puiData);
    	std::swap(m_uiLength, src.m_uiLength)
    

    (also alle Elemente tauschen)

    Ja genau.

    Seh ich richtig, dass somit beim = Operator kein delete mehr nötig ist, da die 2 Objekte getauscht werden und somit das ursprüngliche Objekt(this) zum temporären wird und dieses per Destruktor freigegeben wird?

    Ganz genau. Und das ist auch der große Vorteil davon: Es ist Exception-sicher. Stell Dir vor bei Deiner alten Version klappt zwar das freigeben, aber beim Speicher anfordern (oder Objekte kopieren) fliegt eine Exception. Dann sind Deine alte Daten weg und die neuen kriegste nicht konstruiert. Dein Zustand ist undefiniert. Hier ist es so, dass zunächst der Copy-Konstruktor alle gefährlichen Sachen macht. Fliegt dabei eine Exception ist Dein Objekt noch unverändert. Dann kommt swap, aber das macht nur ungefährliche Sachen, da kann nix fliegen (zumindest sollte man's so implementieren). Danach ist Dein Objekt im neuen Zustand.

    Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?

    Ich mach das immer so. Aber letztlich ist es egal. 🙂



  • Hi,

    Gustav Hummel schrieb:

    ...
    Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?...

    Also ich habe mir das auch angewöhnt, weil man dann mit komplizierteren "const"-trukten ( 😉 ) besser klarkommt.

    Ich merke mir immer "const wirkt rückwärts":

    char const * a; // Zeiger veränderbar, chars NICHT
    char * const b; // Zeiger NICHT veränderbar, chars schon
    char const * const c; // Zeiger NICHT veränderbar, chars auch NICHT
    ...
    const char * d; // aus historischen Gründen identisch mit char const *
    

    Spätenstens bei Funktionspointern wird es ziemlich schnell unübersichtlich, weswegen ich eine einheitliche Schriftweise bevorzuge.

    Gruß,

    Simon2.



  • Super. Wieder was gelernt. Danke allen Beteiligten. 👍

    Gruß
    Gustav



  • Gern geschehen ! 👍

    Gruß,

    Simon2.


Anmelden zum Antworten