2010-07-10 14 views
9

Ho una classe base che dichiara e definisce un costruttore, ma per qualche motivo il mio pubblicamente classe derivata non è visto che il costruttore, e pertanto dichiarare in modo esplicito un costruttore di inoltro nella classe derivata:Perché la sottoclasse C++ necessita di un costruttore esplicito?

class WireCount0 { 
protected: 
    int m; 
public: 
    WireCount0(const int& rhs) { m = rhs; } 
}; 

class WireCount1 : public WireCount0 {}; 

class WireCount2 : public WireCount0 { 
public: 
    WireCount2(const int& rhs) : WireCount0(rhs) {} 
}; 

int dummy(int argc, char* argv[]) { 
    WireCount0 wireCount0(100); 
    WireCount1 wireCount1(100); 
    WireCount2 wireCount2(100); 
    return 0; 
} 

Nel codice precedente, la mia dichiarazione WireCount1 wireCount1(100) viene rifiutata dal compilatore ("Nessuna funzione corrispondente per la chiamata a" WireCount1 :: WireCount1 (int) ""), mentre le mie dichiarazioni wireCount0 e wireCount2 vanno bene.

Non sono sicuro di aver capito perché è necessario fornire il costruttore esplicito mostrato in WireCount2. È perché il compilatore genera un costruttore predefinito per WireCount1 e tale costruttore nasconde il costruttore WireCount0?

Per riferimento, il compilatore è i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659).

risposta

4

Tutte le classi derivate devono chiamare il costruttore della classe base in qualche forma o forma.

Quando si crea un costruttore sovraccarico, il compilatore predefinito generato dal costruttore senza parametri sparisce e le classi derivate devono chiamare il costruttore sovraccaricato.

Quando si ha qualcosa di simile:

class Class0 { 
} 

class Class1 : public Class0 { 
} 

Il compilatore genera effettivamente questo:

class Class0 { 
public: 
    Class0(){} 
} 

class Class1 : public Class0 { 
    Class1() : Class0(){} 
} 

Quando si dispone il costruttore non predefinito, il costruttore senza parametri non è più generato. Quando si definisce la seguente:

class Class0 { 
public: 
    Class0(int param){} 
} 

class Class1 : public Class0 { 
} 

Il compilatore non genera più un costruttore di Class1 a chiamare il costruttore della classe base, è necessario in modo esplicito farlo da soli.

+0

Penso che tu abbia letto male la sua domanda. Non sta chiedendo perché non possa chiamare il costruttore predefinito di Class1, ma piuttosto perché non c'è un costruttore di classi1 (int) da chiamare. – Shirik

+1

Il compilatore genera ancora un costruttore 'Class1()' nel tuo ultimo esempio. È solo che questo costruttore è mal formato se è effettivamente definito (di default come per tutte le funzioni speciali, è dichiarato solo finché non viene effettivamente utilizzato).Puoi verificarlo rendendolo amico: 'classe Class2 {friend Class1 :: Class1(); }; ', che funziona perché il compilatore dichiara implicitamente il costruttore predefinito, indipendentemente dal fatto che possa essere effettivamente chiamato. –

+0

Grazie. Questo mi rende molto chiaro. Anche se apprezzo la risposta di Shirik, credo che il tuo esempio mostri esattamente cosa sta succedendo nel mio codice. –

14

I costruttori non sono ereditati. Devi creare un costruttore per la classe derivata. Il costruttore della classe derivata, inoltre, deve chiamare il costruttore della classe base.

+1

Inoltre, se la classe base ha un costruttore predefinito, il compilatore lo utilizzerà se non si specifica esplicitamente un costruttore nell'elenco di inizializzazione di un costruttore nella classe derivata. –

+0

Grazie. Non mi ero reso conto che i costruttori non erano mai stati ereditati. Mi ero convinto che altri costruttori di classi base (nel codice reale) fossero effettivamente visibili, ma ora lo attribuisco a un gruppo di casting che il compilatore potrebbe aver fatto. –

+0

Mi dispiace che, in quanto newbie, non ho ancora abbastanza punti reputazione per farti scappare la risposta. –

1

Devi costruire la tua classe base prima di occuparti di derivati. Se costruisci la tua classe derivata con costruttori non banali, il compilatore non può decidere cosa chiamare base, ecco perché si verifica un errore.

+0

Un'altra risposta corretta. Grazie. –

Problemi correlati