2015-02-11 7 views
10

Ho il seguente codice:costruttore di copia non è ereditata

class C { 
public: 
    C(int) {} 
    C(const C&) {} 
    C() {} 
}; 

class D : public C { 
public: 
    using C::C; 
}; 

int main() { 
    C c; 
    D d_from_c(c); // does not compile, copy ctor is not inherited 
    D d_from_int(1); // compiles, C(int) is inherited 
} 

classe derivata dovrebbe ereditare tutti ctors di basi tranne il ctor di default (è spiegato here). Ma perché anche il copy ctor non è ereditato? Gli argomenti della domanda correlata non sono accettabili qui.

Il codice è compilato con g ++ 4.8.1.

risposta

12

Perché lo standard dice così. [Class.inhctor]/P3, sottolineatura mia:

Per ogni costruttore non-template nel set candidato del ereditati costruttori diversi da un costruttore non avere parametri o un costruttore copiare/spostare avere un singolo parametro, un costruttore è implicitamente dichiarato con le stesse caratteristiche del costruttore a meno che non esista un costruttore dichiarato dall'utente con la stessa firma nella classe completa in cui viene visualizzata la dichiarazione di utilizzo o il costruttore sarebbe un valore predefinito, una copia o uno spostamento costruttore per quella classe.

10

classe derivata dovrebbe ereditare tutti ctors di basi, tranne il default ctor

No, questo non è vero, vedere T.C.'s answer per la regola reale.

Lo scopo di ereditare i costruttori è di dire "il tipo derivato può essere creato dagli stessi argomenti del tipo di base", ma ciò non è rilevante per il costruttore di copia della classe base, perché un costruttore di copia non è solo un modo per dire come creare un tipo da un determinato argomento.

Un costruttore di copia è speciale, serve per copiare un oggetto dello stesso tipo.

Un costruttore D(const C&) non viene utilizzato per copiare un oggetto dello stesso tipo, poiché C non è dello stesso tipo di D.

0

Per un momento, supponiamo che "l'ereditarietà del costruttore di copie" sia consentita. Avendo la struttura della classe intatta, considerare il seguente codice per il metodo principale modificato.

int main() { 
    C c; 
    D d; 
    D d_from_d(d); 
    D d_from_c(c); // does not compile, copy ctor is not inherited 
    D d_from_int(1); // compiles, C(int) is inherited 
} 

In D d_from_d(d), come una normale chiamata costruttore, ci saranno due chiamate costruttore di copia. Uno per C :: C (const C &) e l'altro per costruttore di copia generato dal compilatore per D. Avendo tipo oggetto di origine in D (d in questo caso), il costruttore di copia di C può copiare gli attributi di C mentre il compilatore genera la copia di il costruttore può copiare l'attributo D di d's.

Ma nel caso D d_from_c(c), Non c'è alcun problema per il costruttore di copie di C perché, gli attributi C di c possono essere copie dal costruttore di copie di C. Ma come ha fatto il compilatore a generare il costruttore di copie di D sa come copiare gli "attributi di D dall'oggetto di C". Questo è un conflitto che dovrebbe essere evitato.

Ma, se si fornisce una sorta di "strano costruttore di copie" (potrebbe essere necessario anche un costruttore predefinito) come;

D(const C & c):C(c){} 

Poi, chiedono D d_from_c(c); è valido. Perché, ora abbiamo esplicitamente fornito un costruttore di "copia" corrispondente.

Quindi, dire "L'ereditarietà dei costruttori di copia ora è consentita" non è valida.