explicit keyword



  • Hi,

    warum macht der compiler ueberhaupt eine implicit type conversion wenn ich folgendes aufrufe?

    Foo f1 = 2;
    

    und explicit sollte das verhindern, was nur bei 1 parameter funktioniert?

    class Foo {
    public:
        explicit Foo(int x) {}
    };
    
    class Bar {
    public:
        Bar(double x) {}
    };
    
    int main() {
        Foo f1 = 2;
    
        return 0;
    }
    


  • gilt das nur wenn ich keinen copy constructor definiere?



  • tobi007 schrieb:

    warum macht der compiler ueberhaupt eine implicit type conversion wenn ich folgendes aufrufe?

    Weil in C++ Konstruktoren, die mit einem Argument aufgerufen werden können und nicht explicit sind, Konvertierungskonstruktoren darstellen. Ist nicht schön, da explicit die Regel und nicht die Ausnahme ist, aber die Einsicht hätte vor zwei Jahrzehnten kommen müssen.

    tobi007 schrieb:

    gilt das nur wenn ich keinen copy constructor definiere?

    Nein, das hat damit nichts zu tun. Kopierkonstruktoren werden nur in Betracht gezogen, wenn das Argument vom gleichen Typ wie die Klasse ist. Der Compiler definiert sowieso Kopierkonstruktoren, wenn er kann und du nichts angibst.



  • warum compiliert dann line 18 nicht? -> error: no matching function for call to ‘Foo::Foo(Foo)’

    #include <iostream>
    using namespace std;
    
    class Foo { 
    public:  
    	Foo(int x) { cout << "Foo constructor" << endl; }
    	Foo(Foo &a) { cout << "Foo copy constructor" << endl; }
    }; 
    
    class Bar { 
    public: 
    	Bar(int x) { cout << "Bar constructor" << endl; }
    }; 
    
    int main() { 
        Foo f1(2); 
      	Foo f2 = f1;
      	Foo f3 = 2; //<--- fails
    
      	Bar b = 2; // implicit convertion
    
        return 0; 
    }
    


  • Weil

    Foo(Foo &a)
    

    kein richtiger Kopierkonstruktor ist*. Du brauchst eine Referenz auf const. Mit der Anweisung

    Foo f3 = 2;
    

    versuchst du, ein temporäres Objekt an eine Referenz auf nicht-konstante Objekte zu binden, was nicht erlaubt ist.

    Darin liegt auch ein subtiler Unterschied zwischen den Deklarationen T var(expr); und T var = expr; . Bei letzterem darf der Compiler T var = T(expr); draus machen. Und auch wenn er es nicht macht, muss dieser Ausdruck kompilieren.

    _______
    * Diese Konstruktorsignatur wurde in C++98 als Hack eingesetzt, um Move-Konstruktoren zu emulieren. Prominentestes Beispiel dieses Idioms ist std::auto_ptr .



  • Wobei allerdings noch anzumerken ist:
    Es wird zwar verlangt, dass dort ein Copyctor existiert, er wird aber nicht aufgerufen, da das wegoptimiert werden kann.



  • @nexus: oh sorry nicht gesehen 🙂

    welchen konstruktorsignatur hack meinst du?


  • Mod

    Nexus schrieb:

    Ist nicht schön, da explicit die Regel und nicht die Ausnahme ist

    Was meinst du damit?

    Kopierkonstruktoren werden nur in Betracht gezogen, wenn das Argument vom gleichen Typ wie die Klasse ist.

    Falsch. Kopierkonstruktoren werden genauso in die Overload-Resolution mit einbezogen wie andere Funktionen. (s. §13.3.1.4)
    Edit:

    kein richtiger Kopierkonstruktor ist*.

    Ebenfalls falsch. Es ist ein Kopierkonstruktor, jedoch kein sinnvoller.

    War das zu nitpickerisch?



  • wie laesst sich folgendes erklaeren?

    Foo f2 = f1; // ... ruft den copy constructor auf 
    Foo f3 = 2; // ... ruft the constructor auf
    


  • ok, sollte nun klar sein.



  • @nexus du meinst ja wohl folgendes?

    T y;
    T x = y; means T x(T(y));
    

Anmelden zum Antworten