8

Potete dirmi il motivo per cui il codice seguente mi sta dando il seguente errore - chiamata del sovraccarico "C (int)" è ambiguoC++ - Funzione di costruzione sovraccarico - privati ​​e pubblici

Vorrei pensare che dal C (char x) è privato, solo il C (float) ctor è visibile dall'esterno e dovrebbe essere chiamato convertendo int in float.

Ma non è questo il caso.

class C 
{ 
    C(char x) 
    { 
    } 
public: 
    C(float t) 
    { 
    } 
}; 

int main() 
{ 
    C p(0); 
} 

risposta

18

Questo è discusso in "Effective C++" di Scott Meyer. La ragione per cui questo è ambiguo è che volevano assicurarsi che la semplice modifica della visibilità di un membro non avrebbe cambiato il significato del codice già esistente altrove.

Altrimenti, supponiamo che la tua classe C fosse in un'intestazione da qualche parte. Se avessi un membro C (int) privato, il codice che hai presentato chiamerebbe C (float). Se, per qualche motivo, il membro C (int) è stato reso pubblico, il vecchio codice lo chiamerebbe improvvisamente, anche se né il codice vecchio né la funzione chiamata erano cambiati.

EDIT: Ulteriori motivi:

Peggio ancora, si supponga di avere le seguenti 2 funzioni:

C A::foo() 
{ 
    return C(1.0); 
} 

C B::bar() 
{ 
    return C(1.0); 
} 

Queste due funzioni potrebbe chiamare funzioni diverse a seconda che sia foo o bar è stato dichiarato come amico di C, o se A o B eredita da esso. Avere identico chiamata di codice diverse funzioni è spaventoso.

(Questo è probabilmente non è così messo in discussione di Scott Meyer, ma questa è l'idea.)

+1

Hmm, questo sembrava un grande spiegazione All'inizio. Ma ... è ancora possibile creare la classe _without_ un int-ctor, poi dopo _add_ quel vecchio codice così vecchio inizia improvvisamente a chiamare il nuovo membro ... Quindi questa protezione crea solo un falso senso di sicurezza. –

+0

Buon punto. Aggiungerò di più –

7

0 è un tipo int. Poiché può essere implicitamente lanciato su un float o su un char ugualmente, la chiamata è ambigua. La visibilità è irrilevante per questi scopi.

o mettere 0.0, 0. o 0.0f, o sbarazzarsi del costruttore C(char) del tutto.

Edit: parte rilevante dello standard, la sezione 13.3:

3) [...] Ma, una volta che le funzioni di candidati e liste di argomenti sono stati identificati, la selezione della migliore funzione è la stessa in tutti i casi:

  • Prima, un sottoinsieme delle funzioni-quelli candidati che hanno il numero corretto di argomenti e soddisfi alcune altre condizioni, è selezionato in modo da formare un insieme di funzioni vitali (13.3.2).
  • Quindi la migliore funzione valida viene selezionata in base alle sequenze di conversione implicite (13.3.3.1) necessarie per far corrispondere ciascun argomento al parametro corrispondente di ciascuna funzione valida.

4) Se esiste una migliore funzione valida ed è unica, la risoluzione del sovraccarico ha esito positivo e produce come risultato. In caso contrario, la risoluzione del sovraccarico fallisce e l'invocazione è mal formata. Quando la risoluzione del sovraccarico ha esito positivo e la migliore funzione vitale non è accessibile (clausola 11) nel contesto in cui viene utilizzata, il programma è mal formato.

Si noti che la visibilità non fa parte del processo di selezione.

+0

Non hai affrontato il motivo per cui la privateness non inclina la risoluzione del sovraccarico. –

+0

+1 questa è la metà della storia, ma non indirizza la visibilità –

+0

Modifica dell'upgrade per la citazione standard. –

-1

Non credo che:

C p(0); 

viene convertito a:

C(float t) 

probabilmente è necessario fare:

C p(0.0f); 
+0

No, non è questo il problema. Esiste una conversione implicita da '0' a float * *. –