2011-09-30 8 views
11

Sono un po 'confuso dopo aver letto qualcosa in un libro di testo. Per quanto riguarda il codice:È un cast o una costruzione?

void doSomeWork(const Widget& w) 
{ 
    //Fun stuff. 
} 

doSomeWork(Widget(15)); 

doSomeWork() prende un parametro const Widget&. Il libro di testo, Effective C++ III, afferma che questo crea un oggetto Widget temporaneo da passare a doSomeWork. Si dice che questo può essere sostituito da:

doSomeWork(static_cast<Widget>(15)); 

come entrambe le versioni sono calchi - la prima è solo un cast di tipo C la funzione a quanto pare. Avrei pensato che Widget(15) avrebbe richiamato un costruttore per il widget prendendo comunque un parametro intero.

Il costruttore potrebbe essere eseguito in questo caso?

risposta

12

In C++ questo tipo di espressione è una forma di cast, almeno sintatticamente. Cioè si utilizza una sintassi di cast funzionale C++ Widget(15) per creare un oggetto temporaneo di tipo Widget.

Anche quando si costruisce un temporaneo utilizzando un costruttore multi-argomento (come in Widget(1, 2, 3)) è ancora considerato una variante del funzionale getto notazione (vedi 5.2.3)

In altre parole, il vostro "Is questa domanda "di getto o di costruzione" è erroneamente affermata, poiché implica un'esclusiva reciproca tra i calchi e le "costruzioni". Non si escludono a vicenda. In effetti, ogni conversione di tipo (che sia un cast esplicito o qualcosa di più implicito) non è altro che una creazione ("costruzione") di un nuovo oggetto temporaneo del tipo di destinazione (escludendo, forse, alcune inizializzazioni di riferimento).

BTW, la notazione di cast funzionale è principalmente una notazione C++. Il linguaggio C non ha cast di stile funzionale.

1

Lei ha detto:

il primo è solo un C cast di tipo funzione apparentemente

Il primo non sarebbe compilare in C, non è C-style. Lo stile C assomiglia a (Widget)15. Qui, l'oggetto temporaneo viene creato utilizzando Widget::Widget(int).

Pertanto, non è un cast in stile C.

+1

@Constantinius: cosa c'è di sbagliato qui? – AnT

+0

Ho modificato la tua risposta. –

-1

Sì. È possibile sostituire

Widget(15) 

con

static_cast<Widget>(15) 

Perché sarà sostituito indietro di compilatore: D

Quando lanci int a Widget compilatore cerca i Widget::Widget(int); e metterlo lì.

5

Abbreviazione: Sì.

lungo:

Si può sempre provare queste cose da soli, facendo ad es .:

#include <iostream> 

struct W 
{ 
    W(int i) 
    { 
     std::cout << "W(" << i << ")\n"; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    W w(1); 
    W(2); 
    static_cast<W>(3); 
} 

che sta emettendo

W(1) 
W(2) 
W(3) 
+0

Il primo non è un cast. Cosa hai provato a mostrare? – MSalters

+2

@MSalters: che per la maggior parte dei tipi un cast non è diverso dalla creazione di un oggetto (temporaneo). – PlasmaHH

+1

@MSalters: Penso che stesse cercando di mostrare la differenza –

3

Sì, è sia :). Un cast è un costrutto sintattico (cioè qualcosa che scrivi). In questo caso, viene invocato un costruttore come conseguenza del cast. Proprio come un costruttore sarebbe invocata come conseguenza di digitare

Widget w(15); 
3

Sia Widget(15) e static_cast<Widget>(15) sono calchi, o di conversione operatori, se si preferisce. Entrambi creano un nuovo oggetto del tipo designato, convertendo 15 in un Widget. Poiché 15 non dispone di operatori di conversione , l'unico modo per eseguire questa conversione è di allocare la memoria necessaria (nello stack) e chiamare il costruttore appropriato . Questo è molto diverso che double(15) e static_cast<double>(15), tranne che di solito non pensiamo double come aventi un costruttore (ma la risultante double è un nuovo oggetto, distinto dal 15, che è di tipo int).

0

Sì, certo. Qualsiasi costruttore prende un singolo parametro sarebbe considerato come CONVERSION CONSTRUCTOR. Il tuo costruttore sta già prendendo un singolo parametro int, in modo che il compilatore possa chiamare "implicitamente" questo costruttore in modo che corrisponda all'argomento (con il valore 15, che è int).

C'è un semplice trucco per prevenire tali errori, basta usare la parola chiave explicit prima del costruttore.

Verificare this per ulteriori informazioni.

Problemi correlati