Fragen zu Konstruktoren



  • Hallo!
    Ich spiele gerade etwas damit rum, um zu lernen und zu verstehen ...
    Nur verstehen tu ich das leider nicht so ganz.

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Klasse
    {
    public:
    	Klasse() : Wert("") { cout << "Standardkonstruktor\n"; }
    	Klasse(const Klasse& tmpcl) : Wert(tmpcl.GetWert()) { cout << "Kopierkonstruktor\n"; }
    	Klasse(const string& neu) : Wert(neu) { cout << "Typumwandlungskonstruktor\n"; }
    	const string& GetWert() const;
    	void SetWert(const string&);
    private:
    	string Wert;
    };
    
    int main()
    {
    	Klasse MyString;
    	MyString.SetWert("Hallo!");
    	cout << "MyString: " << MyString.GetWert() << endl;
    	cin.get();
    	Klasse MyString2 = MyString;
    	cout << "MyString2: " << MyString2.GetWert() << "\tMyString: " << MyString.GetWert() << endl;
    	cin.get();
    	MyString2.SetWert("bla");
    	cout << "MyString2: " << MyString2.GetWert() << "\tMyString: " << MyString.GetWert() << endl;
    	cin.get();
    	MyString = MyString2;
    	cout << "MyString2: " << MyString2.GetWert() << "\tMyString: " << MyString.GetWert() << endl;
    	cin.get();
    	MyString = string("neu");
    	cout << "MyString2: " << MyString2.GetWert() << "\tMyString: " << MyString.GetWert() << endl;
    	cin.get();
    	return 0;
    }
    
    const string& Klasse::GetWert() const
    {
    	return Wert;
    }
    
    void Klasse::SetWert(const string& newWert)
    {
    	Wert = newWert;
    }
    

    Der Code funktioniert so.
    Soweit so gut. Nur verstehe ich folgende Dinge nicht:

    1. Wie oder mit welchem Konstruktor ist es moeglich das MyString.GetWert(); in Zeile 22 wegzulassen, um einfach nur MyString zu schreiben (sodass der Wert 'Wert' einfach zurueckgegeben wird ohne die Methode GetWert() ).

    2. Warum ergibt MyString = "neu" in Zeile 33 einen Compilerfehler? Warum muss hier unbedingt MyString = string("neu") oder MyString = Klasse("neu") stehen? Sollte die Zeichenfolge nicht automatisch zum String konvertiert werden? Ich hab doch gar kein explicit angegeben ...

    3. Warum wird der Kopierkonstruktor nur bei Klasse MyString2 = MyString; ausgefuehrt. Sollte er nicht auch z.b. bei MyString = MyString2; ausgefuehrt werden?

    Weitere Fragen folgen .... ich versteh so manches nich ... leider 😞

    Gruss
    Cartman



  • 1. Gar nicht. Man könnte da etwas mit dem () basteln, macht imo aber nicht viel Sinn.

    2. Das ist keine Initialisierung, sondern eine Zuweisung. Das ist ein essentieller Unterschied. (siehe =-Operator).

    3. Dasselbe Problem, wie bei 2. Es wird der =-Operator (Zuweisungsoperator) aufgerufen, nicht der Konstruktor. (Ist ja bereits Initialisiert).

    EDIT:
    Schreibfehler korrigiert.
    Achja..Schau dir mal "die grossen 3" an:
    http://www.google.ch/search?q=die+grossen+3+c%2B%2B&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla🇩🇪official&client=firefox-a

    Dann sollte dir einiges klarer werden.



  • drakon schrieb:

    1. Gar nicht. Man könnte da etwas mit dem () basteln, macht imo aber nicht viel Sinn.

    Das stimmt so nicht. Für diesen Zweck gibt es Konvertierungsoperatoren.

    Klasse::operator const std::string& () const
    {
        return Wert;
    }
    
    // ...
    std::cout << MyString << std::endl; // implizite Konvertierung nach std::string
    

    Edit: const bei Operator



  • Ich versuch mal kurz zu antworten:

    1.) Durch keinen Konstruktor. Was du machen müsstest, ist einen Cast-Operator zu schreiben.

    2.) Compiler-Fehler, da du keinen Assignment-Operator von Klasse für std::string oder const char* implementiert hast.

    3.) Nein, weil MyString = MyString2 eine Zuweisung ist (wo beide Objekte vorher existieren), während bei Klasse MyString2 = MyString MyString2 erst erzeugt wird. Ist gleichbedeutend mit Klasse MyString2(MyString).

    HTH

    Edit: zu 1.) Es gibt noch zusätzlich die Möglichkeit, die ostream-operatoren zu überladen für deine Klasse

    std::ostream& operator<<(std::ostream&, const Klasse&)
    


  • Nexus schrieb:

    drakon schrieb:

    1. Gar nicht. Man könnte da etwas mit dem () basteln, macht imo aber nicht viel Sinn.

    Das stimmt so nicht. Für diesen Zweck gibt es Konvertierungsoperatoren.

    Stimmt. Ich habe das Beispiel nur schnell überflogen und hatte im Kopf, dass er einen Rückgabewert von Konstruktor haben will. Er hat ja noch nach Konstruktor gefragt. 😉



  • Nexus schrieb:

    drakon schrieb:

    1. Gar nicht. Man könnte da etwas mit dem () basteln, macht imo aber nicht viel Sinn.

    Das stimmt so nicht. Für diesen Zweck gibt es Konvertierungsoperatoren.

    Klasse::operator const std::string& () const
    {
        return Wert;
    }
    
    // ...
    std::cout << MyString << std::endl; // implizite Konvertierung nach std::string
    

    Edit: const bei Operator

    Muss man da noch irgendwas im Klassenkopf deklarieren? Weil so funktioniert das nicht 😞

    Den Rest habe ich verstanden denk ich 🙂

    Danke fuer eure Antworten!

    Gruss
    Cartman



  • Jap. Deklaration gehört in die Klasse.



  • Eric Cartman schrieb:

    Muss man da noch irgendwas im Klassenkopf deklarieren? Weil so funktioniert das nicht 😞

    Ja, der Cast-Operator ist eigentlich eine normale Memberfunktion. Also muss eine Deklaration mit gleicher Signatur in der Klassendefinition erfolgen.

    Mit Konvertierungsoperatoren solltest du allerdings vorsichtig sein: Die Klasse kann so nämlich als String betrachtet werden. Vielleicht gibt es Situationen, wo die implizite Konvertierung nicht erwünscht ist oder sogar zu Konflikten führt; in diesen Fällen ist eine herkömmliche Get-Methode besser geeignet.


Anmelden zum Antworten