2015-08-05 16 views
7

C++ Primer (5a edizione) a pagina 629 stati:Ereditando i costruttori w/wo i loro argomenti predefiniti?

  • Se un costruttore della classe base ha argomenti di default, tali argomenti non vengono ereditati.

Ho provato questo per me stesso e per me sembra che il costruttore derivato generato dal compilatore ha anche gli stessi argomenti di default del costruttore base.

Ecco un piccolo test:

#include <iostream> 

struct Base 
{ 
    Base() = default; 

    Base(int x_, int y_ = 88, int z_ = 99) 
     : x(x_), y(y_), z(z_) {} 

    virtual void debug() const 
    { std::cout << "\nx - " << x << ", y - " << y << ", z - " << z << '\n'; } 

private: 
    int x, y, z; 
}; 

struct Derived : Base 
{ 
    using Base::Base; 
}; 

int main() { 
    Base B(1); 
    B.debug();   // x - 1, y - 88, z - 99 
    Derived D(5); 
    D.debug();   // x - 5, y - 88, z - 99 

    return 0; 
} 

(È possibile eseguire questo qui - http://coliru.stacked-crooked.com/a/26cbb85757c1f021)


Quindi stiamo ereditando anche gli argomenti di default per un costruttore ereditaria o no?
In caso contrario, come mai non sto diventando spazzatura per gli ultimi 2 membri ma gli stessi valori esatti degli argomenti predefiniti per il costruttore ereditato dalla base?
Anche cercato su Internet per una risposta chiara su questo, ma trovato nessuno.

risposta

6

Da [classe.inhctor]:

Il set candidato dei costruttori ereditati dalla classe X denominata nella dichiarazione using è costituito da costruttori effettivi e costruttori nozionali che derivano dalla trasformazione di parametri in default e le specifiche dei parametri puntini di sospensione come segue:
- [...]
- per ogni non-template costruttore della X che disponga di almeno un parametro con un argomento di default, l'insieme di costruttori che deriva da omettendo ogni specifica del parametro puntini di sospensione e successivamente omettendo parametri w on un argomento di default dalla fine del parametro di tipo-list, e
- [...]

Abbiamo due costruttori non-modello di Base. Il costruttore di default della Base introduce il candidato:

Derived() : Base() { } 

E l'altro costruttore di Base introduce un candidato per ogni parametro successivamente omesso. Vale a dire:

Derived(int x, int y, int z) : Base(x, y, z) { } 
Derived(int x, int y)  : Base(x, y) { } 
Derived(int x)    : Base(x) { } 

Gli argomenti di default sono non ereditato - otteniamo appena un costruttore diverso per ogni numero di argomenti. Quindi Derived(5) chiama semplicemente Base(5), non Base(5, 88, 99).

Il risultato finale è lo stesso: il modo in cui ci arriviamo è un po 'diverso.

+0

Ok, ma perché se "Derived (5) chiama semplicemente Base (5), non Base (5, 88, 99)." quando stampo i membri di D ottengo 5, 88, 99? Gli ultimi 2 membri non dovrebbero essere lasciati non inizializzati? – Mugurel

+1

@Mugurel Perché 'Base (5)' chiama 'Base (int x_, int y_ = 88, int z_ = 99)'. 'Derivato' non ha argomenti predefiniti, ma' Base' lo fa ancora. – Barry

+0

"Il risultato finale è lo stesso - il modo in cui arriviamo è un po 'diverso." Pffff :-)))) Grazie! – Mugurel

8

La tua offerta dal libro non è completa.

Se un costruttore della classe base ha argomenti di default (§6.5.1, p. 236), tali argomenti non vengono ereditati. Invece, la classe derivata ottiene più costruttori ereditati in che ogni parametro con un argomento predefinito viene omesso successivamente. Ad esempio, se la base ha un costruttore con due parametri, il secondo dei quali ha un valore predefinito, la classe derivata otterrà due costruttori: uno con entrambi i parametri (e nessun argomento predefinito ) e un secondo costruttore con un singolo parametro corrispondente al il parametro più a sinistra, non in default nella classe base

così classe derivata avrà 3 ereditato costruttori con firme:

Derived (int x): Base{x} {} 
Derived (int x, int y): Base{x, y} {} 
Derived (int x, int y, int z): Base{x, y, z} {} 

E così non siete inh erigendo qualsiasi argomento predefinito dalla classe base.

Derived D(5); 

chiama il primo di questi tre costruttori e costruttore di base è chiamato come

Base(5) 

Si noti inoltre che il valore di default, copiare e spostare i costruttori non sono ereditato. Questi costruttori sono sintetizzati usando le normali regole. Un costruttore ereditato non viene considerato come un costruttore definito dall'utente. Pertanto, una classe che contiene solo costruttori ereditati avrà un costruttore predefinito sintetizzato.

+0

Questo non ha alcuna implicazione sulla mia domanda. – Mugurel

+0

Ho corretto la mia risposta, ora è abbastanza chiara? –

+0

Ottimo! Non l'ho guardato in questo modo. Grazie! Ma perché se Derived D (5) chiama Base (5), quando stampo i membri di D ottengo 5, 88, 99? Gli ultimi 2 membri non dovrebbero essere non inizializzati? – Mugurel

Problemi correlati