2012-02-07 10 views
31

consideri una gerarchia di classi in cui A è la classe base e B deriva da A.Perché il costruttore di copia implicito chiama il costruttore di copia della classe base e il costruttore di copie definito non lo fa?

Se il costruttore di copia non è definito nel B, il compilatore sintetizzerà uno. Quando viene richiamato, questo costruttore di copia chiamerà il costruttore di copia della classe di base (anche quello sintetizzato, se nessuno è stato fornito dall'utente).

#include <iostream> 

class A { 
    int a; 
public: 
    A() { 
     std::cout << "A::Default constructor" << std::endl; 
    } 

    A(const A& rhs) { 
     std::cout << "A::Copy constructor" << std::endl; 
    } 
}; 

class B : public A { 
    int b; 
public: 
    B() { 
     std::cout << "B::Default constructor" << std::endl; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    std::cout << "Creating B" << std::endl; 
    B b1; 
    std::cout << "Creating B by copy" << std::endl; 
    B b2(b1); 
    return 0; 
} 

uscita:

Creating B 
A::Default constructor 
B::Default constructor 
Creating B by copy 
A::Copy constructor 

Se l'utente definisce la propria costruttore di copia in B, quando invocato, questo costruttore di copia chiamerà il costruttore di base classe predefinita, a meno che una chiamata a il costruttore di copia della classe base è esplicitamente presente (ad es. nell'elenco di inizializzazione).

#include <iostream> 

class A { 
    int a; 
public: 
    A() { 
     std::cout << "A::Default constructor" << std::endl; 
    } 

    A(const A& rhs) { 
     std::cout << "A::Copy constructor" << std::endl; 
    } 
}; 

class B : public A { 
    int b; 
public: 
    B() { 
     std::cout << "B::Default constructor" << std::endl; 
    } 
    B(const B& rhs) { 
     std::cout << "B::Copy constructor" << std::endl; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    std::cout << "Creating B" << std::endl; 
    B b1; 
    std::cout << "Creating B by copy" << std::endl; 
    B b2(b1); 
    return 0; 
} 

uscita:

Creating B 
A::Default constructor 
B::Default constructor 
Creating B by copy 
A::Default constructor 
B::Copy constructor 

La mia domanda è: perché non il costruttore di copia definito dall'utente chiamare la copia costruttore della classe base, come un comportamento di default?

+2

Se fosse così per impostazione predefinita, come è possibile specificare il caso in cui non si vuole che ciò accada? – PlasmaHH

+0

@PlasmaHH 'ParentClass()' nell'elenco di inizializzazione. Sarebbe comunque abbastanza inconsistente e confuso credo. –

+0

@ MarkB: In effetti, speravo che arrivasse alla stessa conclusione quando ci pensava ... – PlasmaHH

risposta

7

Questo è solo il modo in cui il costruttore di copia implicita è definita (non avrebbe senso chiamare il default). Non appena si definisce un costruttore (copia o altro), il suo normale comportamento automatico è chiamare il costruttore genitore predefinito, quindi sarebbe incoerente modificarlo per uno specifico costruttore definito dall'utente.

1

La semplice (forse banale) risposta è perché non hai detto a. Dato che stai scrivendo il costruttore di copie derivato, puoi controllare completamente come si comporta. Non è possibile specificare una chiamata alla base e il compilatore genera il codice per inizializzare la classe base chiamando il costruttore predefinito delle classi di base.

8

Tutti i costruttori bambino di base chiamare il costruttore di default genitore. Ecco come viene definito lo standard. Come lei ha sottolineato, se si voleva la classe base B a chiamare costruttore di copia di un dovete esplicitamente richiesto

#include <iostream> 

class A { 
int a; 
public: 
A() { 
    std::cout << "A::Default constructor" << std::endl; 
} 

A(const A& rhs) { 
    std::cout << "A::Copy constructor" << std::endl; 
} 
}; 

class B : public A { 
int b; 
public: 
B() { 
    std::cout << "B::Default constructor" << std::endl; 
} 
B(const B& rhs):A(rhs) { 
    std::cout << "B::Copy constructor" << std::endl; 
} 
}; 

int main(int argc, const char *argv[]) 
{ 
std::cout << "Creating B" << std::endl; 
B b1; 
std::cout << "Creating B by copy" << std::endl; 
B b2(b1); 
return 0; 
} 

Questo perché il compilatore non può sapere per ogni costruttore diversa che constuctor del genitore dovrebbe essere chiamato e quindi abbiamo i costruttori predefiniti Per tutti gli altri devi esplicitamente dichiararli.

+5

'Tutti i costruttori figlio di base chiamano il costruttore predefinito padre. ... eccetto per il costruttore implicito di copie :)! –

+0

Il costruttore di copia implicita è un nome esplicito per un'operazione più primitiva fornita dal compilatore, copia bit per bit di origine a destinazione. IMO è solo un nome di fantasia. – shakthi