2012-02-16 37 views
5

Ho sempre pensato che il costruttore implicito in C++ potesse essere solo un costruttore con un solo argomento. Per esempio:Argomenti impliciti del costruttore

class Foo1 
{ 
    Foo(int); // This could be an implicit constructor 
}; 

Ma è il codice seguente ragione:

class Foo2 
{ 
    Foo2(int, int=0); // Would compiler use this as an implicit constructor? 
} 

posso fare questo:

Foo1 obj; 
... 
obj = 5; 

Che dire Foo2?

+0

Il costruttore esplicito ha un significato diverso. Quello di cui parli riguarda il costruttore con argomenti predefiniti. – Mahesh

+0

@mahesh So che il significato dei costruttori espliciti e la domanda è una domanda :) Va bene, lo riempirò con un esempio. – Ockonal

+4

Nessuno di questi sono costruttori espliciti: non sono contrassegnati con la parola chiave 'explicit'. Intendi * costruttore implicito *? In tal caso, sì, i costruttori possono essere richiamati implicitamente se ai parametri n + 1 vengono assegnati argomenti predefiniti. –

risposta

7

Primo, qualsiasi costruttore può essere contrassegnato con explicit. Quanti argomenti ha è irrilevante.

Con questo fuori strada, ora è necessario capire cosa significa veramente . Significa solo che l'unico modo che il costruttore può essere chiamato è quando si esplicitamente specificare il nome della classe:

struct foo 
{ 
    foo(int){} 
    explicit foo(double){} 
}; 

void bar(foo){} 

bar(5); // okay, calls foo(int) to construct the foo 
bar(3.14); // error, cannot call foo(double) because foo was not explicitly used 
bar(foo(3.14)); // okay, calls foo(double) to construct the foo 

La ragione per cui non segniamo costruttori multipla argomento esplicito è perché è inutile. Dato:

struct baz 
{ 
    baz(int, int, int); 
}; 

Come altro si può chiamare quel costruttore diverso da dire baz comunque? (Come in baz(1, 2, 3).) †

Nel tuo esempio, explicit sarebbe ragionevole perché si poteva chiamata che costruttore con un solo argomento. Ciò che realmente fai dipende solo se ritieni che debba essere implicitamente convertibile o meno.


† Questo non tiene conto degli elenchi di inizializzatori C++ 11. In C++ 11, penso che si potrebbe dire:

void qaz(baz) {} 

qaz({1, 2, 3}); 

e riescono ad ottenere una conversione implicita ad un costruttore a più argomenti, ma io non ne so abbastanza su di inizializzazione-list per fare un commento significativa eccezione come nota a piè di pagina.

+0

Contrassegno sempre tutti i costruttori 'espliciti', per due motivi: la simmetria e la possibilità che un giorno un programmatore possa decidere che tutti tranne il primo argomento potrebbero usare un valore predefinito e aggiungerlo. (Tranne che per i cineasti che io * voglio * naturalmente fare conversioni implicite, cosa che non faccio quasi mai) –

+1

@PaulGroke: non è necessario rendere espliciti tutti i costruttori '. Solo quelli che accettano un argomento, è ciò che penso debba essere contrassegnato come 'esplicito'. – Nawaz

+1

@Nawaz: So che non è necessario, e francamente non sono sicuro di come potresti mai interpretare male il mio commento per giungere alla conclusione che non lo farei. –

2

Se ho capito cosa stai chiedendo, la risposta è sì.

Per essere più specifici, essenzialmente qualsiasi ctor che può essere richiamato con un solo argomento possono e saranno utilizzati per le conversioni implicite. Per evitare ciò, tale agente può essere contrassegnato con explicit. Ciò vale anche per un ctor che accetta un solo argomento, o uno che può richiedere più di un argomento, ma fornisce valori predefiniti per gli altri argomenti.

1

Stai confondendo EXplicit e IMplicit qui. Ciò di cui stai parlando sono costruttori di conversioni. Un costruttore esplicito è esattamente l'opposto: uno che può non essere utilizzato per le conversioni (implicite).

E per rispondere alla tua domanda: sì, Foo2(int, int=0) è un costruttore di conversione che consente la conversione implicita come in obj = 5, becaust può essere chiamato con un int argomento.

Lo stesso vale per i costruttori predefiniti: se si aggiunge anche un valore predefinito per il primo parametro, diventerà anche il costruttore predefinito.

1

Ciò che probabilmente si intende è implicite costruttori, non esplicito.

ogni caso, non si può fare questo (al contrario di quello che si pensa di poter):

Foo1 obj; //this line will not compile as it takes one argument! 
obj = 5; 

Sono sicuro che non hai compilato il codice prima di dire si può fare questo.

Tuttavia, se si intende questo,

Foo1 obj(10); //OK now 
obj = 5; 

Allora sì, è possibile.

Ora che ne dici di Foo2? Bene, you can do so in caso di Foo2 pure:

Foo2 foo(10); 
foo = 5; 
+1

Grazie per il suggerimento sull'errore di compilazione. – Ockonal

Problemi correlati