wieder mal probleme beim überladen (+)



  • Globale operator Funktionen erlauben, mit einigen Voraussetzungen, mehr Freiheit mit weniger Code! 😉

    class Integer
    {
      Integer( int x )
      {}
    
      /* ... */
      Integer operator+( const Integer& ) const
      { /* ... */ }
    };
    
    int main()
    {
      Integer x( 10 );
      Integer y;
    
      y = x + 10; // geht
      y = 10 + x; // geht nicht :)
    }
    

    Jetzt mit globalen Operator+:

    class Integer
    {
      Integer( int x )
      {}
    
      /* ... */
    };
    
    Integer operator+( const Integer&, const Integer& )
    { /* ... */ }
    
    int main()
    {
      Integer x( 10 );
      Integer y;
    
      y = x + 10; // geht
      y = 10 + x; // geht
    }
    


  • Vorteile für globale Funktion:

    • der linke Operand muß kein Klassenobjekt sein (z.B. für die Stream-Opratoren >> und << - die müsstest du als Methoden der IO-Streams definieren und da kommst du nicht ran).
    • auf den linken Operanden können implizite Typumwandlungen angewendet werden (z.B. "Hallo"+str1; funktioniert nicht mit Member-Operator)

    Einziger Nachteil von globalen Operatoren ist, daß sie keinen Sonderzugriff auf private Daten haben - aber wenn man es richtig macht, brauchen sie den auch nicht:

    class MyString
    {
    public:
      MyString operator +=(const MyString& other);
      ...
    }
    
    MyString operator+(const MyString& lhs,const MyString& rhs)
    {
      MyString tmp=lhs;
      return tmp+=rhs;
    }
    


  • CStoll schrieb:

    Einziger Nachteil von globalen Operatoren ist, daß sie keinen Sonderzugriff auf private Daten haben - aber wenn man es richtig macht, brauchen sie den auch nicht

    Zur not kann man die Funktion mit der Klasse befreunden. Wobei das normal eher die letzte Alternative der möglichen Lösungen darstellen sollte.


  • Mod

    CStoll schrieb:

    MyString operator+(const MyString& lhs,const MyString& rhs)
    {
      MyString tmp=lhs;
      return tmp+=rhs;
    }
    

    So aber besser nicht. Hier hat der Compiler keine Chance, (N)RVO anzuwenden.

    MyString operator+(const MyString& lhs,const MyString& rhs)
    {
      MyString tmp=lhs;
      tmp+=rhs;
      return tmp;
    }
    

    ist günstiger.



  • camper schrieb:

    CStoll schrieb:

    MyString operator+(const MyString& lhs,const MyString& rhs)
    {
      MyString tmp=lhs;
      return tmp+=rhs;
    }
    

    So aber besser nicht. Hier hat der Compiler keine Chance, (N)RVO anzuwenden.

    Überhaupt keine ?

    Und wie siehts bei dem hier aus:

    MyString operator+(const MyString& lhs,const MyString& rhs)
    {
      return MyString(tmp) += rhs;
    }
    

  • Mod

    KasF schrieb:

    Überhaupt keine ?

    Und wie siehts bei dem hier aus:

    MyString operator+(const MyString& lhs,const MyString& rhs)
    {
      return MyString(tmp) += rhs;
    }
    

    Gleiches Problem. Der Rückgabewert wird aus dem Funktionsergebnis des += Operators konstruiert und dieses ist kein Objekt (wenn wir mal von einer fehlerfreien Definition von += mit einer Referenz als Rückgabewert ausgehen...).

    Man könnte noch

    MyString operator+(const MyString& lhs,const MyString& rhs)
    {
      MyString tmp=lhs;
      return tmp+=rhs,tmp;
    }
    

    schreiben, aber das ist wohl kaum besser.



  • hmm... aber irgendwie funktioniert keines der angegebenen Beispiele.
    Selbst wenn ich versuche

    astring operator+(const astring& lhs,const astring& rhs) 
    { 
      //astring tmp=lhs; 
      //return tmp+=rhs;
    	return lhs;
    }
    

    bringt er folgenden fehler

    test.cpp(13) : error C2784: "std::_String_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_iterator<_Elem,_Traits,_Alloc>)": template-Argument für "std::_String_iterator<_Elem,_Traits,_Alloc>" konnte nicht von "astring" hergeleitet werden.



  • Bist du sicher, daß genau dieser Operator aufgerufen wird? Wie sieht denn dein dazugehöriges Hauptprogramm aus?

    @camper: Über die Feinheiten des NRVO habe ich mir bisher keinen Kopf gemacht.



  • int main() 
    {
     astring str1 = "Hallo"; 
     astring str2 = " Welt";
     astring str3;
     cout << str1+str2  << endl<< endl;
    
     int länge1=str1.lenght();
     int länge2=str2.lenght();
    
     cout << str1 << endl << str2  << endl<< endl ;
    


  • Und wo genau ist Zeile 13? (btw, hast du eigentlich einen Ausgabe-Operator für astring's definiert?)



  • // stringtest.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "string.h" 
    #include <iostream>
    
    //extern buchstabenliste *beginn1;
    int main() 
    {
     astring str1 = "Hallo"; 
     astring str2 = " Welt";
     astring str3;
     cout << str1+str2  << endl<< endl;
    
     int länge1=str1.lenght();
    

    Hatte nicht alles kopiert.



  • hier nochmal die ausgabe

    ostream& operator<<( ostream& s, const astring& str )		   //ausgeben 
    {
    	astring::buchstabenliste *temp=str.beginn;
    
    	while ((*temp).buchstabe!='#')			//
    	{
    		  s << (*temp).buchstabe; 
            temp=temp->next;
    	}
    	return s;
    }
    

    Den kompletten code hab ich aber auch schonmal gepostet.



  • physikus schrieb:

    Den kompletten code hab ich aber auch schonmal gepostet.

    Inklusive aller in den folgenden zwei Seiten vorgeschlagenen Änderungen? Wie wärs wenn Du mal die Puzzlearbeit selbst machst und nicht uns die erledigen lässt. Also, poste doch einfach mal in einem Post zusammengefasst:

    1. Allen relevanten Sourcecode
    2. Die vollständige Fehlermeldung
    3. Falls die Zeilennummern nicht übereinstimmen exakte Angaben worauf die Meldungen sich beziehen.



  • OK, hier die main

    // stringtest.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "string.h" 
    #include <iostream>
    
    //extern buchstabenliste *beginn1;
    int main() 
    {
     astring str1 = "Hallo"; 
     astring str2 = " Welt";
     astring str3;
     cout << str1+str2  << endl<< endl;
    
     int länge1=str1.lenght();
     int länge2=str2.lenght();
    
     cout << str1 << endl << str2  << endl<< endl ;
     cout << "Die Laenge des ersten strings ist " << länge1 << " Zeichen" << endl<< endl;
     cout << "Die Laenge des zweiten strings ist " << länge2 << " Zeichen" << endl<< endl;
    
     return 0; 
    }
    

    include file

    // stringtest.h: Master include File 
    
    #ifndef STRINGTEST_H_INCLUDED_
    #define STRINGTEST_H_INCLUDED_
    
    #include <iostream>
    #include "string.h"
    using namespace std;
    #endif // define STRINGTEST_H_INCLUDED_
    

    Klasse

    // string.h: Schnittstelle für die Klasse astring
    #include <iostream>
    using namespace std;
    
    #pragma once
    class astring 
    { 
    struct buchstabenliste {
    		char buchstabe;
    		buchstabenliste *next;};
    
    public:
    
    astring ();														//Konstruktor
    
    astring (const char* text );									//Konstruktor
    
    ~astring ();
    
    int lenght();													// gibt die Länge aus
    
    friend ostream& operator<<(ostream&,const astring& str);		//überladen <<
    
    astring operator+(const astring& lhs,const astring& rhs);
    
    private: 
    int size;
    buchstabenliste *beginn;										// beginn der struktur
    };
    

    und die methoden

    // string.cpp: Implementierung der Klasse rational.
    //
    //////////////////////////////////////////////////////////////////////
    
    #include "string.h" 
    
    astring::astring()											  //Konstruktor ohne wert
    {}
    astring::astring(const char *s)								 //Konstruktor einlesen
    {
    	buchstabenliste *temp = new buchstabenliste;  
    	beginn=temp;
    	size=0;
    	for (int i=0;s[i]!='\0';i++)
    		{
    		size++;
    		(*temp).buchstabe=s[i];
    		(*temp).next=new buchstabenliste;
    		temp=temp->next;
    		(*temp).buchstabe='#';
    		}
    }
    astring::~astring()											   //Destruktor
    {}
    int astring::lenght()
    {
    	return size;
    	return 0;
    }
    
    astring operator+(const astring& lhs,const astring& rhs);
    
    { 
      //astring tmp=lhs; 
      //return tmp+=rhs;
    	return lhs;
    }
    /**/
    
    ostream& operator<<( ostream& s, const astring& str )		   //ausgeben 
    {
    	astring::buchstabenliste *temp=str.beginn;
    
    	while ((*temp).buchstabe!='#')			//
    	{
    		  s << (*temp).buchstabe; 
            temp=temp->next;
    	}
    	return s;
    }
    

    so, das wärs, zeilenangaben stimmen alle. Hoffe ihr könnt damit was anfangen und jemand kann mir helfen. Die fehler wären dann

    1>------ Erstellen gestartet: Projekt: stringtest, Konfiguration: Debug Win32 ------
    1>Kompilieren...
    1>string.cpp
    1>e:\studium\2. semester\git ii\eigene software\stringtest\stringtest\string.h(24) : error C2804: Binärer Operator '+' hat zu viele Parameter
    1>e:\studium\2. semester\git ii\eigene software\stringtest\stringtest\string.cpp(33) : error C2447: '{': Funktionskopf fehlt - Parameterliste im alten Stil?
    1>stringtest.cpp
    1>e:\studium\2. semester\git ii\eigene software\stringtest\stringtest\string.h(24) : error C2804: Binärer Operator '+' hat zu viele Parameter
    1>e:\studium\2. semester\git ii\eigene software\stringtest\stringtest\stringtest.cpp(13) : error C2676: Binärer Operator '+': 'astring' definiert diesen Operator oder eine Konvertierung in einen für den vordefinierten Operator geeigneten Typ nicht
    1>Code wird generiert...
    1>Das Buildprotokoll wurde unter "file://e:\Studium\2. Semester\GIT II\Eigene Software\stringtest\stringtest\Debug\BuildLog.htm" gespeichert.
    1>stringtest - 4 Fehler, 0 Warnung(en)
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========

    Compiler: Visual C++ 2005 Express



  • Du mußt den zweistelligen operator+(x, y) außerhalb deiner Klasse definieren, oder aber daraus einen einstelligen machen, der einen impliziten this-Zeiger enthält.



  • kannst du mir ein biesiel geben wie das dann aussieht?
    was wäre denn besser? innerhalb oder außerhalb???



  • astring operator+(const astring& lhs,const astring& rhs);
    

    Diese Zeile aus der Klasse raus nehmen. Und irgendwo außerhalb der Klasse platzieren.



  • so, endlich..... jetzt funktioniert es so halbwegs... kann das programm jetz laufen lassen ... keine fehler mehr..... jetz muss ich nur die methode selbst noch richtig implementieren ......

    astring operator+(const astring& lhs,const astring& rhs);
    

    --> ausehalb der klasse

    astring operator+(const astring& lhs,const astring& rhs)				   
    { 
      //astring tmp=lhs; 
      //return tmp+=rhs;
    	return lhs;
    


  • physikus schrieb:

    so, endlich..... jetzt funktioniert es so halbwegs... kann das programm jetz laufen lassen ... keine fehler mehr..... jetz muss ich nur die methode selbst noch richtig implementieren ......

    gut gesagt mit dem "nur noch".....

    wie mach ich das denn mit dem ausgeben?
    sobald ich z.b return lhs da rein schreibe beendet er das ganze....
    gibts da noch einen trick dabei?

    weil auf den lhs.beginn kann ich auch nicht zugreifen...

    astring::buchstabenliste *temp=str.beginn;
    

    dann sagt er mir immer

    rror C2248: "astring::buchstabenliste": Kein Zugriff auf private struct, dessen Deklaration in der astring-Klasse erfolgte.



  • hat keiner eine idee???


Anmelden zum Antworten