Zuweisungsoperator überladen



  • Wenn ihr das noch nicht hattet, bin ich nicht sicher, ob dein Prof die Lösung anerkennt (kannst ja nachher erzählen, was er erwartet hat).

    Der dynamic_cast dient dazu, quer durch die Vererbungshierarchie umzuwandeln. Der Aufruf versucht, 'other' als eine Unter-Referenz anzusehen. Wenn es wirklich ein Unter-Objekt referenziert, ist alles gut und der normale Zuweisungsoperator wird aufgerufen. Wenn du dort ein Basis-Objekt übergibst, fliegt dir eine bad_cast Exception entgegen.



  • Schmeiß doch ganz kurz google an und such danach. 😉 http://www.google.com/search?q=dynamic_cast&ie=UTF-8&oe=UTF-8



  • Danke dir. Unser Prof ist ist ziemlich locker was das angeht, solange ich erklären kann was genau ich da mache.

    In einer anderen Aufgabe habe ich ein ähnliches Problem:
    Ich habe eine Klasse TextObjekt die einen Überladenen Zuweisungsoperator enthält, der soweit auch funktioniert:

    TextObjekt TextObjekt::operator=(const TextObjekt &T){
    
          if(this == &T){
              return *this;        
          }
          else{
              fileName_out = "2_Verion_von" + T.fileName_out;
              fileName_in = T.fileName_in;
              text = T.text;
              return *this;
          }                 
    }
    

    Aber dann sollen wir eine Funktion schreiben die den Inhalt des Attributs vector<string> text umdreht:

    TextObjekt umdrehen(TextObjekt &T){
    
               vector<string> TextBuffer;
               int i;
               i = text.size();
               while(i--){
                   TextBuffer.at(i) =  text.at(i);
                   cout << "Umgedreht: " << TextBuffer.at(i);          
               }                 
    }
    

    Jetzt habe ich das Problem, dass bei der Zuweisung in der main T2= umdrehen(T1); der Compiler meckert:

    44 C:\Dev-Cpp\bin\10\blatt10_main_c_d_e.cpp no match for 'operator=' in 'T2 = umdrehen(((TextObjekt&)(&T1)))'
    

    Hier macht sich dann wieder mein mangelndes Wissen über die Überladung bemerkbar.



  • In der Funktion fehlt aber eindeutig das return-Statement 😉 Und für die technische Seite empfehle ich dir die Funktionen reverse() und reverse_copy() aus der <algorithm>.

    Was die Fehlermeldung angeht - zeig doch mal etwas mehr Code.



  • Dies ist die ganze Klasse TextObjekt die bisher funktioniert hat(Sorry etwas viel Code). Neu ist nur die Überladung des Zuweisungsoperators ganz unten, der ohne die Funktion umdrehen() (eigene cpp-Datei) auch gefunzt hat:

    // textobject.h
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #ifndef _TEXTOBJECT_H_
    #define _TEXTOBJECT_H_
    using namespace std;
    
    /*---------------------------------------------------------------------------*/
    class TextObjekt{
    
          static int counter;   
          protected:
          vector<string> text;   //Inhalt der Datei
          string fileName_in;
          string fileName_out;     
    
          public:
          string write_mode;
          // Default Konstruktor 
          TextObjekt();         // Erzeugt leeses TextObjekt
          // Konstruktor
          TextObjekt(char* f_in_name, char* f_out_name);
          // Kopierkonstruktor
          TextObjekt(const TextObjekt &kopie);
          // Destruktor
          ~TextObjekt(); 
          // Methoden
          void print_datei(void);
          void set_in_datei(const char *name_in_datei);
          void set_out_datei(const char *name_out_datei);
          string put_string_i(int i);
          char put_char_zeile_spalte(int zeile, int spalte);
          void append_string(string new_string);
          //vector<string> put_text(void);
          void replace(string new_string, int i);
          // Ueberladen des Indexoperator
          string& operator[](int i);
          TextObjekt operator=(const TextObjekt &T);
          void print_alles(void);
          friend void umdrehen(TextObjekt &T);
    };
    
    int TextObjekt::counter = 0;
    
    /*---------------------------------------------------------------------------*/
    
    TextObjekt::TextObjekt(){
    
        fileName_in = "no_in_file";
        fileName_out = "no_out_file";
        text.clear();
        counter ++;
        cout << "**Defaultkonstruktor TextObjekt**: (" << counter << ")"<< endl;
    
    }
    
    TextObjekt::TextObjekt(char* f_in_name, char* f_out_name){
    
        text.clear();
    
        fileName_in = string(f_in_name);
        fileName_out = string(f_out_name);
        set_in_datei(f_in_name);
        //set_in_datei(fileName_in.c_str());
    
        counter ++;
        cout << "**Konstruktor TextObjekt**: (" << counter << ")"<< endl;                 
    }
    
    TextObjekt::TextObjekt(const TextObjekt &kopie){
    
        //fileName_in = kopie.fileName_in;
    	//fileName_out = kopie.fileName_out;
        text = kopie.text;
        text.clear();
        fileName_out = "Kopie_von_" + kopie.fileName_out;
        fileName_in = kopie.fileName_in;
        counter ++;
        cout << "**Kopierkonstruktor TextObjekt**: (" << counter << ")" << endl;                 
    }
    TextObjekt::~TextObjekt(){
    
        if(strcmp(fileName_out.c_str(),"no_out_file") == true){
      		set_out_datei(fileName_out.c_str());
       	}
        counter --;
        cout << "**Destruktor TextObjekt**: (" << counter << ")" << endl;              
    }
    void TextObjekt::print_datei(void){
    
             for(int i=0; i<text.size(); i++){
                 cout << text.at(i) << endl;  
             }
    }
    // Datei einlesen
    void TextObjekt::set_in_datei(const char *name_in_datei){
        // Datei nur zum Lesen oeffnen
    
        ifstream fin;
        string buffer2;
    
        fileName_in = string(name_in_datei);  //string erzeugen
        text.clear(); // Loescht alle Elemente
    
        fin.open(fileName_in.c_str());     // formatiert den Dateinamen in ein Zeichenkette-Format
        if(!fin){ 
              cout << "Konnte Datei nicht oeffnen!" << endl; 
        }
        else {
             while(getline(fin, buffer2)){ // Inhalt einlesen
             text.push_back(buffer2);             
             }
        }
        fin.close();  
    }
    void TextObjekt::set_out_datei(const char *name_out_datei){
        //Datei zum Schreiben oeffnen
        fstream fout;
        fileName_out = string(name_out_datei);
    
        	if(write_mode != "out"){	
    		ofstream foutapp(fileName_out.c_str(),ios::app);
    		if(!foutapp){
    	   		cout << "Feherhaft geoeffnete Datei" << endl;
    		   return;
    		}
    
    		for(int i = 0 ; i < text.size() ; i++){
    			foutapp << text.at(i)<<endl;
    		}
    		foutapp.close();
    	}
    	else{
    		ofstream fout(fileName_out.c_str());
    		if(!fout){
    	   		cout << "Feherhaft geoeffnete Datei" << endl;
    		   return;
    		}
    
    		for(int i = 0 ; i < text.size() ; i++){
    			fout << text.at(i)<<endl;
    		}
    		fout.close();
    	}
    
      	cout << "Datei gespeichert in: " << fileName_out << endl;
    
        /*fout.open(fileName_out.c_str());      // formatiert den Dateinamen in ein Zeichenkette-Format
        if(fout.good()){ 
    
             for(int i=0; i<text.size(); i++){
                     fout << text.at(i) << endl; // in Filestream speichern        
             }
             cout << "Datei gespeichert in Datei: " << fileName_out << endl;
             fout.close();
        }
        else {
             cout << "Konnte Datei nicht oeffnen!" << endl;             
        }*/
    }
    
    string TextObjekt::put_string_i(int i){
    
       	if(text.size() > i)   // genug Zeilen vorhanden?
             return text.at(i-1);
        else
    	return "Zeile nicht vorhanden";
    }
    char TextObjekt::put_char_zeile_spalte(int zeile, int spalte){
    
    	if(text.size() > zeile && text.at(zeile-1).size() > spalte && zeile >= 0 && spalte >= 0){
    		return text.at(zeile-1).at(spalte-1);
    	}
    
    	cout << "exestiert nicht" << endl;
        return '\0';
    
    }
    // String anhaengen
    void TextObjekt::append_string(string new_string){
    
         text.push_back(new_string); // new_string an text haengen 
    }
    void TextObjekt::replace(string new_string, int i){
    
        if(text.size() > i)   // genug Zeilen vorhanden?
             text[i-1]=new_string;
        else cout << "Zeile nicht vorhanden!" << endl;        
    }
    string& TextObjekt::operator[](int i){
    
          if((i>=0) && (i<text.size())){
              return text[i];          
          }
          else
          cout << "?" << endl;      
    }
    TextObjekt TextObjekt::operator=(const TextObjekt &T){
    
          if(this == &T){
              return *this;        
          }
          else{
              fileName_out = "2_Verion_von_" + T.fileName_out;
              fileName_in = T.fileName_in;
              text = T.text;
              return *this;
          }                 
    }
    void TextObjekt::print_alles(void){
    
         cout << "File_out_name: " << fileName_out << endl;
         cout << "File_in_name: " << fileName_in << endl;          
    }
    
    #endif
    


  • Interessanter ist im Moment eher die main()-Funktion.

    Und wie gesagt: in der umdrehen() fehlt eine return-Anweisung (oder soll der Compiler erraten, was er zurückgeben soll?).



  • Lol nee, also return T;
    In der main steht nicht viel drin.

    int main(){
    
      int a = 0;  
    
    	TextObjekt T1("kurzes_gedicht.txt","machmichnichtkaputt.txt"), T2; 
    
    	// Ausgabe des Inhalts: 
    	cout << endl << "Ausgabe T1 vor dem Aufruf der Funktion:" << endl << endl; 
    	T1.print_datei(); 
    	cout << endl << "Ausgabe T2 vor dem Aufruf der Funktion:" << endl << endl; 
    	T2.print_datei(); 
    
    	T1.set_out_datei("machmichnichtkaputt.txt"); 
    
    	// umdrehen von T1: 
    	T2= umdrehen(T1); 
    
        cin >> a; 
    
    	cout << "Ende main ! " << endl; 
    
    	return 0; 
    }
    


  • Mit dem Inhalt der Funktion mußt du dich nochmal genauer beschäftigen - du packst den vector-Inhalt rückwärts in eine lokale Variable und gibt dann deinen Urprungszustand zurück.



  • Um ehrlich zu sein hab ich mir bei der Funktion keine großartigen Gedanken gemacht, wie man sieht. Hab das ganze Wochenende nur Aufgaben in C++ für morgen gelöst und nu geht nix mehr.

    Wenn ich also ein bischen nachdenke müsste ich doch so der Sache ein bischen näher kommen:

    TextObjekt umdrehen(TextObjekt &T){
    
               int i;
               i = text.size();
               while(i--){
                   text.at((text.size())-i) =  text.at(i);
                   cout << "Umgedreht: " << text.at(i);          
               }
          return T;                 
    }
    


  • Wenn du beabsichtigst, die Daten im Ursprungsobjekt umzudrehen, geht es in die richtige Richtung. Aber dabei zerhaust du dir leider dein Array, weil du Teile überschreibst, bevor sie gelesen werden.

    TextObjekt umdrehen(TextObjekt &T)
    {
        TextObjekt T2 = T;
        reverse(T2.text.begin(),T2.text.end());
        return T2;
    }
    

    Was die Funktion macht, kannst du selber herausfinden 😉



  • Aber was hat es mit der Fehlermedlung auf sich? Ich habe doch einen überladenen Zuweisungsoperator. Oder ist der auch falsch? Oder muss es für jede Operation einen eigenen geben? Ich check das mit dem Überladen irgendwie net.
    sorry für meine lange Leitung gestern.
    Gruß Dominika

    44 C:\Dev-Cpp\bin\10\blatt10_main_c_d_e.cpp no match for 'operator=' in 'T2 = umdrehen(((TextObjekt&)(&T1)))'
    

Anmelden zum Antworten