wieder mal probleme beim überladen (+)



  • Hallo
    Ich habe eine Klasse erzeugt in die ich einen string in einzelnen buchstaben in eine verkettete liste einlesen kann.

    struct buchstabenliste {
    		char buchstabe;
    		buchstabenliste *next;};
    

    nun möchte ich 2 dieser strings aneinander "kleben" durch +, wozu ich + ja überladen muss. Mein Ansatz:

    int main() 
    {
     astring str1 = "Hallo"; 
     astring str2 = " Welt";
     astring str3;
     cout << str1+str2  << endl<< endl; 
    
    astring operator +(astring& str);
    private: 
    int size;
    
    astring::astring operator +(astring& str)
    {
    	return 0;
    }
    

    1. Wenn ich das nur soweit mache bekomme ich schon dutzende Fehlermeldungen. Ist da schon grundsätzlich was falsch?

    2. Die eigentliche Methode: ich kopiere den 1. string in einen neuen string. dann öffne ich die kette und füge den 2 hinten dran.
    Aber dazu brauche ich doch die beiden zeiger der beiden strings, wie bekomme ich die?

    gruß



  • hier findet ihr den restlichen code des programms

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-184172.html



  • Hi!

    Mach den Operator global:

    const astring operator+( const astring& lhs, const astring& rhs )
    {
      // lhs und rhs zusammenfuegen und neues stringobjekt zurueckgeben
    }
    


  • David_pb schrieb:

    Hi!

    Mach den Operator global:

    const astring operator+( const astring& lhs, const astring& rhs )
    {
      // lhs und rhs zusammenfuegen und neues stringobjekt zurueckgeben
    }
    

    wenn ich das so mache kommt direkt

    error C2804: Binärer Operator '+' hat zu viele Parameter



  • lasse ich einfach einen parameter weg und versuche testweise

    const astring operator+( const astring& lhs) 
    
    {
    	return lhs;
    }
    

    dann sagt er

    error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: class astring const __thiscall astring::operator+(c



  • Zeigmal den Rest deines Codes.



  • 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;
    
    #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 <<
    
    const astring operator+( const astring& lhs); 
    
    private: 
    int size;
    buchstabenliste *beginn;										// beginn der struktur
    
    };
    
    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;
    }
    const astring operator+( const astring& lhs) 
    {
    	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;
    }
    


  • Du sprichst schon wieder von einer globalen Funktion als Methode. Global definierte Operatoren sind in der Regel friends der Klasse auf der sie operieren.

    Warum eröffnest du eigentlich für dein Thema wenn ich richtig gezählt habe drei Threads!?



  • kenner der dummköpfe schrieb:

    Du sprichst schon wieder von einer globalen Funktion als Methode. Global definierte Operatoren sind in der Regel friends der Klasse auf der sie operieren.

    so wirklich versteh ich das nicht. heißt das ich muss das auch mit dem friend machen?
    was macht dieses friend eigentlich ???

    Warum eröffnest du eigentlich für dein Thema wenn ich richtig gezählt habe drei Threads!?

    weil es vll immer um verschiedene probleme geht?!?



  • Aber immer das selbe Programm, oder?

    Entweder du machst die Operatorfunktion global oder du schreibst astring::operator+ etcpp.



  • was heißt denn global machen??



  • physikus nicht böse gemeint, aber so wird das nie mit C++. Ich weiß nicht wie du schon zu Klassen und Operatoren-Überladung gekommen bist, ohne einfach Sachen wie global zu wissen.

    Wahrscheinlich frickelst du dir alles zurecht und holst mal hier und da Infos/Tipps bis es funktioniert.

    Ließ dir ein anständiges Tutorial oder Buch durch.
    Empfehlung: http://www.cpp-tutor.de/cpp/intro/toc.htm



  • Global (mein C++ wissen bisher) heist das eine Funktion oder Variable ungebunden unabhängig auserhalb Klassen definiert werden, und so vom gesamten Code aus sichtbar und verwendbar sind.

    //Globale Funktion
    void Globfunk(){
    
    };
    
    class A{
    
    void funk();
    };
    
    //klassen Member (gebunde Funktion an Klasse)
    void A::funk(){
    
    }
    
    class B{
    
    void funk();
    
    }; 
    
    //klassen Member (gebunde Funktion an Klasse)
    void B::funk(){
    
    }
    


  • OK, und welche vor bzw nachteile oder sinn und zweck hat es wenn ich das überladen von + global oder halt nicht global mache?



  • 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.


Anmelden zum Antworten