2009-10-18 18 views
14

¿Tenemos que definir explícitamente un constructor predeterminado cuando definimos un constructor de copia para una clase? Por favor, den razones.Copy Constructor y constructor predeterminado

por ejemplo:

class A 
{ 
    int i; 

    public: 
      A(A& a) 
      { 
       i = a.i; //Ok this is corrected.... 
      } 

      A() { } //Is this required if we write the above copy constructor?? 
};  

Además, si definimos cualquier otro constructor con parámetros para una clase que no sea el constructor de copia, es lo que también hay que definir el constructor por defecto ?? Considere el código anterior sin el constructor de copia y reemplazarlo con

A(int z) 
{ 
    z.i = 10; 
} 

Alrite .... Después de ver las respuestas que escribió el siguiente programa.

#include <iostream> 

using namespace std; 

class X 
{ 
    int i; 

    public: 
      //X(); 
      X(int ii); 
      void print(); 
}; 

//X::X() { } 

X::X(int ii) 
{ 
    i = ii; 
} 


void X::print() 
{ 
    cout<<"i = "<<i<<endl; 
} 

int main(void) 
{ 
    X x(10); 
    //X x1; 
    x.print(); 
    //x1.print(); 
} 

Y este programa parece funcionar bien sin el constructor predeterminado. Por favor, explica por qué es este el caso? Estoy realmente confundido con el concepto .....

+2

Estoy confundido. Aunque la respuesta a continuación es correcta, no es un constructor de copias. ¿Dónde estás copiando 'i', exactamente? Está modificando el lado derecho, que generalmente es lo incorrecto. Deberías hacer 'A (const A & rhs): i (rhs.i) {}', eso es copiar el 'i' del lado derecho en esta instancia de 'i' de A'. Tenga en cuenta que los parámetros se pasan por constante, porque cuando dice algo como x = 3, 3 no debería cambiar. Además, generalmente los tipos numéricos se pasan por valor, no como referencia, porque las referencias pueden ser más lentas para los tipos de datos pequeños. – GManNickG

+0

Wow ... Gracias por su comentario ... despejó la confusión sobre la parte ": i (rhs.i)" del constructor que me ha estado confundiendo desde que empecé a estudiar constructores esta mañana ... –

+1

Su El último programa no usa el constructor predeterminado en ninguna parte. Por esta razón, no necesita definirlo. Eso es todo lo que hay. – AnT

Respuesta

33

Sí. Una vez que declara explícitamente absolutamente cualquier constructor para una clase, el compilador deja de proporcionar el constructor predeterminado implícito. Si aún necesita el constructor predeterminado, tiene que declararlo y definirlo usted mismo.

P.S. Es posible escribir un constructor de copia (o un constructor de conversión, o cualquier otro constructor) que también sea constructor predeterminado. Si el constructor new entra en esa categoría, no hay necesidad de proporcionar un constructor adicional por defecto más :)

Por ejemplo:

// Just a sketch of one possible technique  
struct S { 
    S(const S&); 
    S(int) {} 
}; 

S dummy(0); 

S::S(const S& = dummy) { 
} 

En el ejemplo anterior el constructor de copia es al mismo tiempo el constructor por defecto .

+0

"Es posible escribir un constructor de copia que también sea constructor predeterminado". ¿Cómo? – dalle

+0

Al agregar un argumento predeterminado a un copiador, por ejemplo. Vea el ejemplo que agregué a mi respuesta. – AnT

+0

¿Puedes aclarar mi pregunta editada? El código funciona bien sin definir el constructor predeterminado. –

3

No tiene que definir ambos. Sin embargo, una vez que define cualquier constructor para una clase, todos los predeterminados dejan de estar disponibles. Entonces, si quiere copiar-construir y construir sin copiar, necesita definir un constructor no predeterminado (es decir explícito) por defecto (es decir, sin parámetros) también.

Si define un constructor de copia, normalmente también debe anular el operador de asignación.

+0

Estás confundiendo el problema al sobrecargar la palabra "predeterminada". No solo eso, sino que su significado de incumplimiento sobrecargado se explicó con la palabra "explícito", que es otra palabra clave reservada para uso con constructores. Puede usar sintetizado en su lugar (con una z si lo prefiere). :) – Troubadour

+0

La sobrecarga de la palabra "por defecto" fue deliberada, es triste que no tenga sentido del juego de palabras. En cuanto a la palabra "explícito", la existencia de significados especializados dentro del lenguaje C++ no invalida los significados preexistentes dentro del idioma inglés. Y en cuanto a "sintetizado", ¿pensé que el objetivo debía ser entendido? – Steve314

1

Como dijo AndreyT, si declara explícitamente cualquier constructor, incluido un constructor de copia, el compilador no declarará implícitamente ni definirá un constructor predeterminado.

Esto no siempre es un problema.

Si no desea que su clase sea predecible, entonces está perfectamente bien no declarar un constructor predeterminado. Pero si desea que sea predeterminado-construible (por ejemplo, si desea descomentar la línea X x1; en su ejemplo), entonces debe declarar y definir un constructor predeterminado.

También tenga en cuenta que un constructor predeterminado es cualquier constructor que se puede llamar sin argumentos, no solo uno sin argumentos. X::X(int = 5) es un constructor predeterminado perfectamente fino.

0

1) El constructor sin argumento se denomina 'Constructor predeterminado'. 2) Si el usuario no ha proporcionado ninguno de los siguientes constructores, entonces el compilador declara el constructor predeterminado para usted.

2a) Copy Constructor 
    2b) Non-default constructor 
    2C) default constructor. 

3) Si los compiladores declara el 'constructor por defecto', entonces se dice que es 'implícitamente declaró el incumplimiento del constructor',

4) El 'constructor por defecto declarado implícitamente' son de dos tipos

4a) **trivial** Constructor 
    4b) **non-trivial** Constructor. 

5) implícitamente declarado constructor predeterminado se dice que es 'trivial', cuando hay 5a) No de referencia variable 5b) No virtual Función 5c) No base de la Clase virtual. 5d) clase dominante tiene constructor de 'trivial',

Else, it is said to be 'non-trivial'. 

Espero que esto ayude.

Cuestiones relacionadas