Operator overloading - was ist falsch?



  • Hallo,

    ich lerne die Basics vom Operator overloading. Soweit verstehe ich dass 3 * string zum Beispiel "a a a" erzeugen kann: http://coliru.stacked-crooked.com/a/97cbaf4638283343

    Nun habe ich ein Beispiel mit 3 * MyClass und erhalte aber keine erweiterte Liste sondern einen Fehler... was mache ich falsch:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class B {
    	
    	public:
    	
    	B(const string & _n) : name(_n) {}
    	
    	friend ostream & operator<<(ostream & out, const B & b);
    	
    	private:
    	
    	  string name;
    	
    	
    };
    
    ostream & operator<<(ostream & out, const B & b) {
    	cout << b.name << endl;
    	
    	return cout;
    }
    
    class C {
     
       public:
       
         C(const B & b) {
             
               data.push_back(b);
         }
         
         void print() const {
             for (size_t i=0; i < data.size(); i++) {
                 cout << data[i] << endl;
             }
         }
         
         /*
         C operator+=(const C & c) {
    		 return *this + c;
    	 }
    	 * */
         
         friend const C operator*(int n, const C & a);
         
      private:
        
         std::vector<B> data;
         
        
    };
    
    const C operator*(int n, const C & a) {
        C c(a);
        for (int m=0; m < n; m++) {
            c.data.push_back( a.data[m] );
        }
        return c;
    }
    
    int main() {
        
        cout << "hello" << endl;
        C a(3 * B("world"));
     
        a.print();
     
       return 0;   
    }
    


    1. Fehler:
      Du postest nicht, was Du für einen Fehler erhältst 😕

    Aber so beim schnellen Überfliegen sieht es für mich so aus, als ob Du

    3 * ein Objekt vom Typ B
    

    'rechnen' willst.
    B kennt aber den Operator '*' gar nicht ...



  • @patrickm123 sagte in Operator overloading - was ist falsch?:

    sondern einen Fehler... was mache ich falsch:

    Du verschweigst Details.



  • Ich habe nicht versucht den Code zu verstehen. Nur, was mir sofort ins Auge gestochen ist:

    @patrickm123 sagte in Operator overloading - was ist falsch?:

    const C operator*(int n, const C & a) {
    

    Was glaubst Du bringt das erste const da?

    @patrickm123 sagte in Operator overloading - was ist falsch?:

    ostream & operator<<(ostream & out, const B & b)
    {
    	cout << b.name << endl;
    	return cout;
    }
    

    Wofür ist hier der Parameter out?

    @patrickm123 sagte in Operator overloading - was ist falsch?:

    Nun habe ich ein Beispiel mit 3 * MyClass und erhalte aber keine erweiterte Liste sondern einen Fehler...

    Hast Du denn verstanden was der operator*() in Deinem Beispiel

    @patrickm123 sagte in Operator overloading - was ist falsch?:

    const string operator*(int n, const string & s) {
        string s2;
        for (int m=0; m < n; m++) {
            s2 += "  " + s;
        }
        return s2;
    }
    

    tut?



  • This post is deleted!


  • @Swordfish sagte in Operator overloading - was ist falsch?:

    const C operator*(int n, const C & a) {

    Mit dem "const" will ich vorbeugen dass eine Expression wie (a*b) = 4 möglich ist, war im Kontext LValues vs RValues wie hier S. 299 beschrieben

    Mit

    ostream & operator<<(ostream & out, const B & b)
    

    Bezwecke ich dass ich << verketten kann,

    cout << a << b << endl;
    

    Ja, der Operator * soll die Funktion operator* aufrufen. Das Ergebenisse in C weggeschrieben werden. Und dann die Ausgabe "Hello world world world"... es kommt aber nur ein Hello World, vermutlich wird das Ergebnis nicht weggeschrieben. Kann später nochmal einen Versuch starten.



  • @patrickm123 sagte in Operator overloading - was ist falsch?:

    Mit dem "const" will ich vorbeugen dass eine Expression wie (a*b) = 4 möglich ist, war im Kontext LValues vs RValues wie hier S. 299 beschrieben

    Das geht sowieso nicht weil es weder für deine C- noch für Deine B-Hugos einen Konstruktor gibt der einen int nimmt. (Und wenn es möglich wäre, es wäre sch***-egal. Das zurückgegebene Dingsti ist ein temporary ... kratzt niemanden.)

    @patrickm123 sagte in Operator overloading - was ist falsch?:

    Mit
    ostream & operator<<(ostream & out, const B & b)

    Bezwecke ich dass ich << verketten kann,

    Ja. Schön. Und für was ist der Parameter out?

    @patrickm123 sagte in Operator overloading - was ist falsch?:

    vermutlich wird das Ergebnis nicht weggeschrieben.

    Du hast einen Logikfehler in deiner Multiplikationiererei.

    #include <vector>
    #include <string>
    #include <iostream>
    
    class B
    {
    	std::string name;
    
    public:
    	B(std::string const &name = "")  // identifier mit unterstrichen ... lass das. 1)
    	: name{ name }
    	{}
    
    	friend
    	std::ostream& operator<<(std::ostream &out, B const &b)
    	{
    		return out << b.name;
    	}
    
    	friend B operator*(int n, B const &b)
    	{
    		B result;
    		auto foo { b.name };
    		for (int i = 0; i < n; ++i)
    			result.name += (i ? " " : "") + foo;
    		return result;
    	}
    };
    
    class C
    {
    	std::vector<B> data;
    
    public:
    	C(B const &b)
    	: data{ b }
    	{}
    
    	void print() const
    	{
    		for (auto const &d : data)
    			std::cout << d << '\n';
    	}
    };
    
    int main()
    {
    	std::cout << "hello\n";
    	C a{ 3 * B("world") };
    	a.print();
    }
    

    Ich weiß aber nicht warum C einen vector<B> haben soll oder was das ganze werden soll wenn's fertig ist. Operatorüberladungen ausprobieren? Mach's mit Typen wo's Sinn macht ....

    1. [lex.name]/3.2, Ja, es ist nicht global scope, aber trotzdem. Besonders in einem Konstruktor ist es hässlich und bringt genau garnichts.


  • Danke für dein beispiel!
    Ja, jetzt habe ich noch eine Variante gefunden, die * mit + .. + .. + .. identisch ist. In der Tat geht es nur um ein Verständnis vom Overloading:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class B {
    	
    	public:
    	
    	B(const string & n) : name(n) {}
    	
    	friend ostream & operator<<(ostream & out, const B & b);
    	
    	private:
    	
    	  string name;
    	
    	
    };
    
    ostream & operator<<(ostream & out, const B & b) {
    	out<< b.name << endl;
    	
    	return out;
    }
    
    class C {
     
       public:
       
    	 C() {
    		 
    	 }
    	 
         C(const B & b) {
               data.push_back(b);
         }
         
         void print() const {
             for (size_t i=0; i < data.size(); i++) {
                 cout << data[i] << endl;
             }
         }
         
    
         
         
         friend const C operator*(int n, const C & a);
    
    	 friend const C operator+(const C & a, const C & b) ;
    	 
    	 friend const C operator*(int n, const B & b) ;
    	 
      private:
        
         std::vector<B> data;
         
        
    };
    
    const C operator*(int n, const C & a) {
        C c(a);
        
        for (int m=1; m < n; m++) {
            c.data.push_back( a.data[0] );
        }
        return c;
    }
    
    const C operator*(int n, const B & b) {
        C c;
        
        for (int m=0; m < n; m++) {
            c.data.push_back( b );
        }
        return c;
    }
    
    const C operator+(const C & a, const C & b) {
    	C z(a);
    	for (size_t i=0; i < b.data.size(); i++) {
    		z.data.push_back(b.data[i]);		
    	}
    	
    	return z;
    }
    
    int main() {
        
        cout << "hello" << endl;
        C a1(  C(B("world")) + C(B("world")) + C(B("world")));
        
        
    	cout << "-----" << endl;
        a1.print();
     
    	cout << "-----" << endl;
        
        C a2( 3 * B("world"));
        a2.print();
     
       return 0;   
    }
    
    

    Danke für Dein Feedback zum Init-Liste Style, den muss ich beim nächsten Mal umsetzen.


Log in to reply