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 constructor que no está declarado con el especificador explicit y que puede ser llamado con un solo parámetro (until C++11) se denomina converting constructor .

A diferencia de los constructores explícitos, que solo se consideran durante la inicialización directa (que incluye conversiones explícitas como static_cast ), los constructores de conversión también se consideran durante la inicialización por copia , como parte de la secuencia de conversión definida por el usuario .

Se dice que un constructor de conversión especifica una conversión implícita de los tipos de sus argumentos (si los hay) al tipo de su clase. Nótese que las funciones de conversión definidas por el usuario no explícitas también especifican una conversión implícita.

Los constructores de copia y los constructores de movimiento implícitamente declarados y definidos por el usuario no explícitos son constructores de conversión.

Ejemplo

struct A
{
    A() { }         // constructor de conversión (desde C++11)  
    A(int) { }      // constructor de conversión
    A(int, int) { } // constructor de conversión (desde C++11)
};
struct B
{
    explicit B() { }
    explicit B(int) { }
    explicit B(int, int) { }
};
int main()
{
    A a1 = 1;      // OK: la inicialización por copia selecciona A::A(int)
    A a2(2);       // OK: la inicialización directa selecciona A::A(int)
    A a3{4, 5};    // OK: la inicialización directa de lista selecciona A::A(int, int)
    A a4 = {4, 5}; // OK: la inicialización por copia de lista selecciona A::A(int, int)
    A a5 = (A)1;   // OK: el cast explícito realiza static_cast, inicialización directa
//  B b1 = 1;      // error: la inicialización por copia no considera B::B(int)
    B b2(2);       // OK: la inicialización directa selecciona B::B(int)
    B b3{4, 5};    // OK: la inicialización directa de lista selecciona B::B(int, int)
//  B b4 = {4, 5}; // error: la inicialización por copia de lista seleccionó un constructor explícito
                   //        B::B(int, int)
    B b5 = (B)1;   // OK: el cast explícito realiza static_cast, inicialización directa
    B b6;          // OK, inicialización por defecto
    B b7{};        // OK, inicialización directa de lista
//  B b8 = {};     // error: la inicialización por copia de lista seleccionó un constructor explícito
                   //        B::B()
    [](...){}(a1, a4, a4, a5, b5); // puede suprimir advertencias de "variable no utilizada"
}

Véase también