Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

C++11 Niejawna konwersja z lista inicjalizacyjną

Ostatnio zmodyfikowano 2017-12-27 19:55
Autor Wiadomość
latajacaryba
Temat założony przez niniejszego użytkownika
C++11 Niejawna konwersja z lista inicjalizacyjną
» 2017-12-17 13:44:12
Witam. Czytałem o listach inicjalizacyjnych. Problem jest taki, że nie działa ponizszy kod:
C/C++
#include <iostream>

using namespace std;

class C
{
    int a;
    int b;
    double c;
   
public:
   
    C( double a, double b, double c )
    {
        this->a = a;
        this->b = b;
        this->c = c;
        cout << "konstruktor z 3 double\n";
    }
   
    explicit C( std::initializer_list < double > iList )
    {
        auto i = iList.begin();
        this->a = * i;
        if( i != iList.end() )
             ++i;
       
        this->b = * i;
        if( i != iList.end() )
             ++i;
       
        this->c = * i;
        cout << "konstruktor listy\n";
    }
   
    void Print()
    {
        cout << "a: " << a << " b: " << b << " c: " << c << "\n";
    }
   
};

int main()
{
    C obj = { 3.6, 3.4, 3.2 }; // blad
    obj.Print();
    return 0;
}


\C++11\main.cpp|51|error: converting to 'C' from initializer list would use explicit constructor 'C::C(std::initializer_list<double>)'|

Nie wiem dlaczego, w książce ("C++ Biblioteka standardowa") wszystko działa. Tutaj niejawna konwersja z użyciem listy inicjalizacyjnej jest niemożliwa, bez konstruktora przyjmującego listę inicjalizacyjną, lub gdy jest on explicit. Natomiast nie wiem, dlaczego nie może być użyty w zamian konstruktor z 3 double'ami (w końcu lista zawiera 3 double i wg. książki jest to możliwe).
P-167946
Luq
» 2017-12-17 14:15:40
P-167948
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-12-22 01:41:50
Na początku przepraszam, źle przeczytałem i przykład z książki zawiera niewielką, ale jednak znaczącą różnicę.

Jak rozumiem, jest to zrobione w ten sposób, aby gdy konstruktor listy jest explicit (czyli nie chcemy niejawnych konwersji z listy na obiekt), to nie może być użyty, jak np. w powyższym przypadku - konstruktor z 3 doublami, bo byłby swoistym backdoorem - dałoby się zastosować niejawną konwersję dla list mającej 3 double. Możliwe?
P-168053
Monika90
» 2017-12-22 16:57:39
Prawdopodobnie masz rację. W przypadku inicjalizacji bez listy tak nie jest, co prowadzi do dziwnych zachowań:
C/C++
struct X
{
    explicit X( double ) { }
    X( int ) { }
};

int main()
{
    X x = 5.5;
}
Tutaj będzie wywołany konstruktor z parametrem int, a byłoby lepiej gdyby C++ traktowało to jako błąd. No i w przypadku inicjalizacji za pomocą listy projektanci C++ tak właśnie zrobili:
C/C++
#include <initializer_list>

struct X
{
    explicit X( std::initializer_list < int > ) { }
    X( int ) { }
};

int main()
{
    X x = { 5 }; //ERROR!
}

Konstruktor z parametrem typu initializer_list ma pierwszeństwo, co więcej, jeżeli kompilator go wybierze, to trzyma się tego nawet jeśli za chwilę się okaże, że nie można tego konstruktora użyć bo jest on explicit (lub private). Inne konstruktory nie są już wtedy brane pod uwagę i mamy błąd kompilacji.


P-168062
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-12-27 19:55:59
Dziękuje w takim razie. Temat zamykam.
P-168156
« 1 »
  Strona 1 z 1