2009-06-04 11 views
10

Ho visto codice come il seguente frequentemente in qualche codice C++ sto guardando:Qual è lo scopo di digitare una classe in C++?

typedef class SomeClass SomeClass; 

stumped quanto a che cosa questo realmente realizza. Sembra che questo non cambierebbe nulla. Cosa fanno in questo modo typedef? E se questo fa qualcosa di utile, ne vale la pena?

+4

forse dovresti chiedere a quella persona? piuttosto che chiedere a tutti tranne quella persona. – DevinB

+0

Volevo ottenere un consenso se ne valeva la pena, piuttosto che la spiegazione di una persona. –

+0

E il ragazzo in realtà si sbagliava. "non tag nasconde il nome del tag in C++" - né true in C, né true in C++. Per qualche ispirazione, leggi questo rapporto sui difetti http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 –

risposta

7

Vedere questa risposta precedente a una domanda correlata. E 'una lunga citazione da un articolo di Dan Saks che spiega la questione nel modo più chiaro come qualsiasi cosa che abbia mai incontrato:

Difference between 'struct' and 'typedef struct' in C++?

La tecnica può prevenire i problemi reali (anche se i problemi certamente raro).

E 'un po' poco di assicurazione - è a costo zero in fase di esecuzione o in spazio di codice (l'unico costo è i pochi byte nel file di origine), ma la protezione che si ottiene è così piccolo che è raro vedere qualcuno usarlo costantemente. Ho uno snippet di "nuova classe" che include il typedef, ma se effettivamente codifico una classe da zero senza usare lo snippet, non mi preoccupo quasi mai (o si ricorda?) Di aggiungere typedef.

Quindi direi sono d'accordo con la maggior parte delle opinioni qui riportati - vale la pena di mettere quelle typedef, ma non basta che darei a nessuno (me compreso) il dolore di non metterli in

.

mi è stato chiesto per un esempio di come non avere un nome di classe typedef'ed può causare un comportamento imprevisto - ecco un esempio sollevato più o meno dall'articolo Saks:

#include <iostream> 
#include <string> 

using namespace std; 

#if 0 // change to #if 1 to get different behavior 
     // imagine that this is buried in some header 
     // and even worse - it gets added to a header 
     //  during maintenance... 
string foo() 
{ 
    return "function foo... \n"; 
} 
#endif 

class foo 
{ 
public: 
    operator string() { 
     return "class foo...\n"; 
    } 
}; 

int main() 
{ 
    string s = foo(); 

    printf("%s\n", s.c_str()); 
    return 0; 
} 

Quando la dichiarazione di funzione è fatto visibile, il comportamento del programma cambia in modo silenzioso perché non vi è alcun conflitto di nomi tra la funzione foo e la cla ss foo.

Tuttavia, se si include "typedef class foo foo;", si otterrà un errore di compilazione anziché una differenza di comportamento non presidiata.

+0

Devi farlo molte cose per cui questo accada che sono tentato di dire che te lo meriti! Il numero uno fornirebbe cast di conversione invece di utilizzare funzioni con nome (sempre un no-no, IMHO). –

+2

Gli operatori di conversione potrebbero essere un no-no, ma non sono affatto rari. Ad ogni modo, non discuterò le "tante cose devono andare storte". Come ho detto, non è qualcosa su cui insisto nel codice di mio o di chiunque altro. Ma volevo spiegare perché è nel codice dell'OP (questa era la domanda dopo tutto), e sottolineare che il typedef non ha costi e non causa problemi. In effetti, rende i compilatori un po 'più simili alle aspettative della gente, anche se sono rimasto sorpreso dal comportamento di alcuni compilatori nel frammento di Adam. Penso che il documento collegato da litb sia educativo a riguardo. –

+0

Questo è davvero interessante; le risposte che ho ottenuto a questa domanda mi rendono felice di aver posto questa domanda qui. –

0

Sembra che il commento stia cercando di affermare che typedef rende il simbolo SomeClass globale in un modo che impedisce a chiunque di essere in grado di dichiarare un oggetto locale con lo stesso nome che nasconde il SomeClass originale.

Ho provato questo con VC6 (non un vero compilatore C++ lo so, ma il migliore che ho ATM), e non sembra fare molto. SomeClass rimane nascosto da una dichiarazione locale con lo stesso nome. Forse cambia il contenuto di un messaggio di errore per alcuni compilatori per renderlo più utile.

-2

capisco il concetto di diversi spazi dei nomi che tag e identificatori vivono, ma questo è davvero anche vale la pena di digitarlo?

No.

+6

(-1) Assolutamente nessuna spiegazione o ragionamento. Avrei potuto facilmente scrivere "Sì". e l'unica differenza sarebbe stata la reputazione. – DevinB

+0

Non ti piace la mia risposta (lui, dopo tutto, ha esposto il ragionamento), scrivi la tua. –

0

Sembra a me come il tuo collega non abbia pienamente laureato da C.

In C, se si dichiara struct foo {int a;};, non avete nulla si può chiamare semplicemente foo , ma piuttosto struct foo. Pertanto, è abbastanza comune digitare typetf struct foo come foo.

Questo è stato modificato in C++, per motivi che dovrebbero essere abbastanza ovvi.

+1

È possibile, ma in realtà non definirei il comportamento di C "nascondere il nome". –

20

Previene codice come questo da compilare:

class SomeClass { ... }; 
int SomeClass; 

Questo è perfettamente legale C++, anche se è terribile. Se si esegue questa operazione, qualsiasi riferimento a SomeClass si riferisce alla variabile. Per fare riferimento alla classe, è necessario dire esplicitamente class SomeClass ad ogni utilizzo. Se si crea un typedef:

class SomeClass { ... }; 
typedef class SomeClass SomeClass; 
int SomeClass; 

Poi i flag di compilazione la definizione di int SomeClass come un errore, come giustamente dovrebbe essere.

+0

Il secondo esempio viene compilato per me (VC2005). –

+3

Problema con VC++ quindi non dovrebbe essere compilato. –

+0

Interessante, funziona effettivamente con un compilatore che uso (e non con MSVC) – Dolphin

0

O compilatore veramente rotto o qualcuno che non sa cosa fanno, o almeno così penserei.

+0

O qualcuno che sa qualcosa che molte persone non sanno ... –

6

Adam ha fornito la ragione corretta per farlo, ma per quanto riguarda la tua domanda "Vale la pena" darei un clamoroso "No!".L'eventuale codice di problema:

class SomeClass { ... }; 
int SomeClass; 

sarà catturato quando un po 'più tardi qualcuno dice:

SomeClass sc; 

Devo ammettere che il compilatore punterà sulla linea di "sbagliato", ma questo genere di cose accade così raramente (Non credo di averlo mai visto in codice reale) che non può giustificare una foresta di typedef quasi superflui.

+0

Grazie per aver risposto a quella domanda, questo è quello che volevo davvero sapere. Non l'avevo mai visto prima, quindi avevo la sensazione che non ne sarebbe valsa la pena. –

+0

Se si omette il typedef, è possibile che non si verifichi sempre un errore, sebbene le situazioni siano rare. Una funzione con lo stesso nome di una classe può nascondere qualcosa che altrimenti sarebbe un costruttore di classi. –

+0

Potresti pubblicare un esempio di questo - Non riesco a visualizzare come sarebbe possibile. –