Namespaces
Variants

Converting constructor

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Un constructeur qui n'est pas déclaré avec le spécificateur explicit et qui peut être appelé avec un seul paramètre (until C++11) est appelé constructeur de conversion .

Contrairement aux constructeurs explicites, qui ne sont considérés que lors de l'initialisation directe (ce qui inclut les conversions explicites telles que static_cast ), les constructeurs de conversion sont également pris en compte durant l'initialisation par copie , dans le cadre d'une séquence de conversion définie par l'utilisateur .

On dit qu'un constructeur de conversion spécifie une conversion implicite des types de ses arguments (s'il y en a) vers le type de sa classe. Notez que les fonctions de conversion définies par l'utilisateur non-explicit spécifient également une conversion implicite.

Les constructeurs de copie et les constructeurs de déplacement implicitement déclarés et définis par l'utilisateur non-explicites sont des constructeurs de conversion.

Exemple

struct A
{
    A() { }         // constructeur de conversion (depuis C++11)  
    A(int) { }      // constructeur de conversion
    A(int, int) { } // constructeur de conversion (depuis C++11)
};
struct B
{
    explicit B() { }
    explicit B(int) { }
    explicit B(int, int) { }
};
int main()
{
    A a1 = 1;      // OK : l'initialisation par copie sélectionne A::A(int)
    A a2(2);       // OK : l'initialisation directe sélectionne A::A(int)
    A a3{4, 5};    // OK : l'initialisation directe par liste sélectionne A::A(int, int)
    A a4 = {4, 5}; // OK : l'initialisation par copie de liste sélectionne A::A(int, int)
    A a5 = (A)1;   // OK : le cast explicite effectue un static_cast, initialisation directe
//  B b1 = 1;      // erreur : l'initialisation par copie ne considère pas B::B(int)
    B b2(2);       // OK : l'initialisation directe sélectionne B::B(int)
    B b3{4, 5};    // OK : l'initialisation directe par liste sélectionne B::B(int, int)
//  B b4 = {4, 5}; // erreur : l'initialisation par copie de liste a sélectionné un constructeur explicite
                   //        B::B(int, int)
    B b5 = (B)1;   // OK : le cast explicite effectue un static_cast, initialisation directe
    B b6;          // OK, initialisation par défaut
    B b7{};        // OK, initialisation directe par liste
//  B b8 = {};     // erreur : l'initialisation par copie de liste a sélectionné un constructeur explicite
                   //        B::B()
    [](...){}(a1, a4, a4, a5, b5); // peut supprimer les avertissements "variable inutilisée"
}

Voir aussi