Klasseninstanz mit '=' erzeugen?



  • Hallo!

    ich bin gerade bei einer Übungsaufgabe, bei der ich eine Klasse erstellen soll, die mit brüchen rechnet. Die main()-Funktion ist schon vorgegeben und soll lauffähig sein, wenn die Klasse geschrieben wurde.

    Hier die Vorgabe:

    #include <iostream>
    #include “Bruch_MN.h“
    
    using namespace std;
    
    int main()
    {
        CBruch br1 = “1/3“, br2 = “2/5“, br;
        cout << “Ausgabe: “ << br << endl; // Ausgabe: 0
        cout << br1 << “ + “ << br2 << “ = “ << br1 + br2 << endl; // Ausgabe: 1/3 + 2/5 = 11/15
        cin >> br; // Eingabe: 2/10 oder auch 2 / 10
        cout << “Ausgabe: “ << br << endl; // Ausgabe: 1/5
        br = 2;
        cout << “Ausgabe: “ << br << endl; // Ausgabe: 2/1
        cout << 1.0 * br1 << endl; // Ausgabe: 0.4
        cout << br1 * 1.0 << endl; // Ausgabe: 0.4
        cout << “HN: “ << br1 % br2 << endl; // HN: 15
        return 0;
    }
    

    Mich irretiert die Erzeugung der Klasseninstanzen:

    CBruch br1 = “1/3“, br2 = “2/5“, br;
    

    Kann das so funktionieren? Ich habe dazu nichts finden können. Ich habe es so verstanden, dass die Klasse 'CBruch' heißt und mit dieser Zeile die Instanzen br1, br2 und br erstellt werden sollen.
    Wie kann ich jetzt die Zeichen hinter dem '=' an eine Funktion in der Klasse übergeben? Z.B. dem Konstruktor.

    Vielen Dank für eure Hilfe!



  • Class foo = something;
    

    ist exakt dasselbe wie

    Class foo(something);
    

    Hilft dir das weiter?


  • Mod

    Sie werden bereits an den Konstruktor übergeben. In einer Initialisierung der Form

    T a = b;
    

    Wird der Wert des Ausdrucks b an den besten impliziten Konstruktor von T übergeben um a zu initialisieren, das ganze nennt man Kopierinitialisierung (engl. copy initialization). (Falls du noch nicht weißt was implizite und explizite Konstruktoren sind, ignoriere das Wörtlein)



  • Hi Nathan,

    danke! Das hilft 🙂


  • Mod

    Das ist ungefähr* eine Abkürzung für

    CBruch br1(CBruch("1/3"));
    

    *: Es werden nicht wirklich 2 Instanzen (br1 und das temporäre Objekt) erzeugt, sondern br1 wird gleich richtig erzeugt. Es müssen aber zumindest die passenden Funktionen vorhanden sein, auch wenn sie wegoptimiert werden.


  • Mod

    Nathan schrieb:

    Class foo = something;
    

    ist exakt dasselbe wie

    Class foo(something);
    

    Nicht ganz:

    struct Foo
    {
    	Foo(int){}	
    	Foo(const Foo&) = delete;
    };
    
    int main()
    {
    	Foo foo(1);
    	Foo foo2 = 2;  // Fehler, Kopierkonstruktor fehlt
    }
    

    Aber:

    #include <iostream>
    struct Foo
    {
    	Foo(int){}	
    	Foo(const Foo&){std::cout << "Copy called\n"; }
    };
    
    int main()
    {
    	Foo foo(1);
    	Foo foo2 = 2;
    }
    

    Führt trotzdem zu keiner Ausgabe 🙂 .



  • SeppJ schrieb:

    Aber:

    #include <iostream>
    struct Foo
    {
    	Foo(int){}	
    	Foo(const Foo&){std::cout << "Copy called\n"; }
    };
    
    int main()
    {
    	Foo foo(1);
    	Foo foo2 = 2;
    }
    

    Führt trotzdem zu keiner Ausgabe 🙂 .

    Semantisch exakt dasselbe.



  • Kann es sein, dass abhängig von der Schreibweise der Bruch als C String (const char []) und C++ String aufgewasst wird?

    Wenn ich es mit

    CBruch br1 = "1/3";
    

    und

    CBruch(string sBruch)
    

    mache, kommt beim kompilieren der Fehler

    conversion from 'const char [4]' to non-scalar type 'CBruch' requested

    Schreibe ich allerdings

    CBruch br1("1/3");
    

    funktioniert es.

    Verstehe ich das richtig, dass das eine einen C String und das andere einen C++ String erzeugt, oder gibt es da etwas anderes, was ich übersehen habe?

    Danke für eure Hilfe!



  • Flaeshi schrieb:

    Verstehe ich das richtig, dass das eine einen C String und das andere einen C++ String erzeugt, [...]

    ein "sonstwas" ist immer ein char const [N] ... bis damit vielleicht ein std::string erzeugt wird.

    Flaeshi schrieb:

    [...] oder gibt es da etwas anderes, was ich übersehen habe?

    Zeig doch mal class CBruch ...



  • Die Klasse sieht so aus:

    class CBruch
    {
    private:
        int iZaehler;
        unsigned int iNenner;
        void kuerzen();
    
    public:
        CBruch();
        CBruch(string sBruch);
    
        int get_zaehler();
        unsigned int get_nenner();
    
        void set_variables(string sBruch);
    
        CBruch& operator+(CBruch const& lhs);
        CBruch& operator-(CBruch const& lhs);
        CBruch& operator*(CBruch const& lhs);
        CBruch& operator/(CBruch const& lhs);
    
        friend string operator*(float lhs, CBruch const& rhs);
        friend string operator*(CBruch const& lhs, float rhs);
        friend unsigned int operator%(CBruch const& lhs, CBruch const& rhs);
    
        CBruch& operator=(const char* temp);
        CBruch& operator=(int temp);
    
    };
    

    Am besten wäre es, wenn ich den String nicht erst in einen C++ String umwandeln muss (so habe ich es vorher gemacht). Die Erstellung der Instanz darf ich nämlich nicht verändern.



  • SeppJ schrieb:

    Aber:

    #include <iostream>
    struct Foo
    {
    	Foo(int){}	
    	Foo(const Foo&){std::cout << "Copy called\n"; }
    };
    
    int main()
    {
    	Foo foo(1);
    	Foo foo2 = 2;
    }
    

    Führt trotzdem zu keiner Ausgabe 🙂 .

    natürlich nicht, aber mach' mal

    Foo(int) = delete;
    


  • Flaeshi schrieb:

    Kann es sein, dass abhängig von der Schreibweise der Bruch als C String (const char []) und C++ String aufgewasst wird?

    Wenn ich es mit

    CBruch br1 = "1/3";
    

    und

    CBruch(string sBruch)
    

    mache, kommt beim kompilieren der Fehler

    conversion from 'const char [4]' to non-scalar type 'CBruch' requested

    Schreibe ich allerdings

    CBruch br1("1/3");
    

    funktioniert es.

    Hi,

    das Problem hier sollte sein, dass der Parameter maximal einmal implizit konvertiert werden darf.
    Im ersten Fall muesste er aber von char[n] nach std::string konvertiert werden und dann von std::string nach CBruch.

    Im zweiten Fall wird char[n] nach std::string konvertiert und dafuer gibt es einen Konstruktor.

    Ich hoffe das stimmt so. Schon ein bissle her das ich das im Effective C++ gelesen hab.

    Um das zu fixen einfach noch einen Konstruktor bauen der einen char* entgegen nimmt.

    CBruch(char const * const str) 
       : CBruch( std::string(str) ) 
    {}
    

    Gruessle


Anmelden zum Antworten