Espacios de nombres
Variantes
Acciones

Constructores por defecto

De cppreference.com
< cpp‎ | language
 
 
 
 

Un constructor por defecto es un constructor que se puede llamar sin argumentos (ya sea definido con una lista de parámetros vacía, o con argumentos por defecto proporcionados para cada parámetro). Un tipo con un constructor público por defecto es DefaultConstructible.

Contenido

[editar] Sintaxis

nombre_de_clase ( ) ; (1)
nombre_de_clase :: nombre_de_clase ( ) cuerpo (2)
nombre_de_clase() = delete ; (3) (desde C++11)
nombre_de_clase() = default ; (4) (desde C++11)
nombre_de_clase :: nombre_de_clase ( ) = default ; (5) (desde C++11)

Donde nombre_de_clase debe denominar la clase actual (o la instanciación actual de una plantilla de clase), o, cuando se declara en un ámbito de espacio de nombres o en una declaración friend, debe ser un nombre de clase calificado.

[editar] Explicación

1) Declaración de un constructor por defecto dentro de una definición de clase.
2) Definición del constructor fuera la definición de la clase (la clase debe contener una declaración (1). Véase constructores y listas de inicializadores de miembros para más detalles acerca del cuerpo del constructor.
3) Constructor por defecto eliminado: si se selecciona por la resolución de sobrecarga el programa falla al compilar.
4) Constructor por defecto predeterminado: el compilador definirá el constructor por defecto implícito, aún si otros constructores están presentes.
5) Constructor por defecto predeterminado fuera de la definición de la clase (la clase debe contener una declaración (1). Tales constructores se tratan como proporcionados por el usuario (véase a continuación e inicialización de un valor).

Los constructores por defecto se llaman durante las inicializaciones por defecto y las inicializaciones por valor.

[editar] Constructor por defecto implícitamente declarado

Si no se proporcionan constructores de cualquier tipo declarados por el usuario para un tipo clase (struct, class, o union), el compilador siempre declarará un constructor por defecto como un miembro inline public de su clase.

Si se encuentran presentes algunos constructores declarados por el usuario, el usuario aún puede forzar la generación automática de un constructor por defecto por el compilador que de lo contrario sería declarado implícitamente con la palabra clave default.

(desde C++11)

El constructor por defecto declarado implícitamente (o predeterminado en su primera decflaración) tiene una especificación de excepción como se describe en especificación de excepción dinámica (hasta C++17)especificación de excepción (desde C++17)

[editar] Constructor por defecto implícitamente definido

Si el constructor por defecto implícitamente declarado no está definido como eliminado (= delete), se define (es decir, se genera y se compila un cuerpo de función) por el compilador si hay uso ODR o es necesario para la evaluación constante (desde C++11), y tiene el mismo efecto que un constructor definido por el usuario con un cuerpo vacío y una lista de inicializadores vacía. Es decir, llama a los constructores por defecto de las bases y de los miembros no estáticos de esta clase. Si esto satisface los requisitos de un constructor constexpr, el constructor generado es constexpr. (desde C++11) Los tipos clase con un constructor vacío proporcionado por el usuario pueden tratarse de manera diferente que aquellos con un constructor definido implícitamente o constructor por defecto predeterminado (= default) durante la inicialización de un valor.

Si se encuentran presentes algunos constructores definidos por el usuario, el usuario aún puede forzar la generación automática de un constructor por defecto por el compilador que, de lo contrario, sería implícitamente declarado con la palabra clave default.

(desde C++11)

[editar] Constructor por defecto implícitamente declarado eliminado

El constructor por defecto implícitamente declarado o predeterminado (= default) (desde C++11) para una clase T está indefinido (hasta C++11)definido como eliminado (desde C++11) si cualquiera de lo siguiente es verdadero:

  • T tiene un miembro de tipo referencia sin un inicializador por defecto. (desde C++11)
  • T tiene un miembro const no construible por defecto constante si un inicializador de miembro por defecto (desde C++11).
  • T tiene un miembro (sin un inicializador de miembro por defecto) (desde C++11) que tiene un constructor por defecto eliminado, o su constructor por defecto es ambiguo o inaccesible desde este constructor.
  • T tiene una clase base directa o virtual que tiene un constructor por defecto eliminado, o es ambiguo o inaccesible desde este constructor.
  • T tiene una clase base directa o virtual, o un miembro de datos no estático, que tiene un destructor eliminado, o un destructor que es inaccesible desde este constructor.
  • T es una union con al menos un miembro variante con un constructor por defecto no trivial, y ningún miembro variante de T tiene un inicializador de miembro por defecto.
  • T es una clase no-unión con un miembro variante M con un constructor por defecto no trivial, y ningún miembro variante de la unión anónima que contiene a M tiene un inicializador de miembro por defecto.
(desde C++11)
  • T es una union y todos sus miembros variantes son const.

Si no se encuentran presentes constructores definidos por el usuario y el constructor por defecto implícitamente declarado no es trivial, el usuario aún puede inhibir la generación automática de un constructor por defecto implícitamente definido por el compilador con la palabra clave delete.

(desde C++11)

[editar] Constructor por defecto trivial

El constructor por defecto para una clase T es trivial (p. ej., no realiza ninguna acción) si todo lo siguiente es verdadero:

  • El constructor no es proporcionado por el usuario (p. ej., es implícitamente definido o por defecto en su primera declaración).
  • T no tiene funciones miembro virtuales.
  • T no tiene clases base virtuales.
(desde C++11)
  • Cada base directa de T tiene un constructor trivial por defecto.
  • Cada miembro no estático de tipo clase (o array de los mismos) tiene un constructor trivial por defecto.

Un constructor trivial por defecto es un constructor que no realiza ninguna acción. Todos los tipos de datos compatibles con el lenguaje C (tipos POD, o plain-old data types) son trivialmente construibles por defecto.

A diferencia de C, los objetos con constructores por defecto triviales no pueden crearse simplemente reinterpretando apropiadamente el almacenamiento alineado, como memoria asignada con std::malloc: se requiere de new para formalmente introducir un nuevo objeto y evitar un comportamiento potencialmente indefinido.

[editar] Constructor por defecto seleccionable

Un constructor por defecto es seleccionable si es declarado por el usuario o declarado implícitamente y definible.

(hasta C++11)

Un constructor por defecto es seleccionable si no está eliminado (= delete).

(desde C++11)
(hasta C++20)

Un constructor por defecto es seleccionable si

(desde C++20)

La trivialidad de los constructores por defecto seleccionables determina si la clase es un tipo con tiempo de vida implícito, y si la clase es un tipo trivial.

[editar] Ejemplo

struct A 
{
    int x;
    A(int x = 1): x(x) {} // constructor por defecto definido por el usuario
};
 
struct B: A 
{
    // B::B() es implícitamente definido, llama a A::A()
};
 
struct C 
{
    A a;
    // C::C() es implícitamente definido, llama a A::A()
};
 
struct D: A 
{
    D(int y): A(y) {}
    // D::D() no se declara porque existe otro constructor
};
 
struct E: A 
{
    E(int y): A(y) {}
    E() = default; // explícitamente por defecto, llama a A::A()
};
 
struct F {
    int& ref;    // miembro referencia
    const int c; // miembro const
    // F::F() es implícitamente definido como eliminado
};
 
// el constructor de copia declarado por el usuario (ya sea proporcionado por el usuario,
// eliminado o por defecto) evita la generación implícita de un constructor por defecto
 
struct G
{
    G(const G&) {}
    // G::G() implícitamente definido como eliminado
};
 
struct H
{
    H(const H&) = delete;
    // H::H() implícitamente definido como eliminado
};
 
struct I
{
    I(const I&) = default;
    // I::I() implícitamente definido como eliminado
};
 
int main() 
{
    A a;
    B b;
    C c;
//  D d; // ERROR en tiempo de compilación
    E e;
//  F f; // ERROR en tiempo de compilación
//  G g; // ERROR en tiempo de compilación
//  H h; // ERROR en tiempo de compilación
//  I i; // ERROR en tiempo de compilación
}


[editar] Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
CWG 2084 C++11 Los inicializadores de miembro por defecto no tienen
efecto en si un constructor por defecto
predeterminado de una unión se elimina)
Evitan que el constructor por defecto predeterminado
se defina como eliminado

[editar] Véase también