2009-06-04 14 views
10

Ich habe Code gesehen, wie die folgenden häufig in einigen C++ Code Ich betrachte:Was ist der Zweck von typedefing eine Klasse in C++?

typedef class SomeClass SomeClass; 

ich ratlos bin, was diese tatsächlich erreicht. Es scheint, als würde das nichts ändern. Was macht typedef s so? Und wenn das etwas Sinnvolles tut, ist es den zusätzlichen Aufwand wert?

+4

vielleicht sollten Sie diese Person fragen? anstatt alle außer dieser Person zu fragen. – DevinB

+0

Ich wollte einen Konsens darüber finden, ob es das wirklich wert ist, und nicht die Erklärung einer Person. –

+0

Und der Typ war eigentlich falsch. "Nicht-Tag versteckt den Tag-Namen in C++" - weder wahr in C noch wahr in C++. Für einige Inspiration, lesen Sie diesen Fehlerbericht http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 –

Antwort

7

Siehe diese vorherige Antwort auf eine verwandte Frage. Es ist eine lange Zitat aus einem Dan Saks Artikel, der dieses Problem so klar wie alles erklärt ich kenne:

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

Die Technik tatsächlichen Probleme verhindern kann (obwohl zugegebenermaßen selten Probleme).

Es ist ein billiges Stück Versicherung - es kostet keine Kosten zur Laufzeit oder im Coderaum (die einzigen Kosten sind die wenigen Bytes in der Quelldatei), aber der Schutz ist so klein, dass es ungewöhnlich ist, jemanden zu sehen konsequent. Ich habe ein "neues Klassen" -Snippet, das das Typedef enthält, aber wenn ich tatsächlich eine Klasse von Grund auf neu programmiere, ohne das Snippet zu verwenden, mache ich mir fast keine Mühe (oder erinnere ich mich?), Das Typedef hinzuzufügen.

Also würde ich sagen, dass ich mit den meisten der Meinungen nicht einverstanden sind hier gegeben - es lohnt sich, diese typedefs in, aber nicht genug setzen, dass ich jemand geben würde (mich eingeschlossen) Trauer um sie nicht bei der Umsetzung

.

ich habe ein Beispiel dafür, wie man einen Klassennamen mit typedef kann zu unerwartetem Verhalten führt gefragt - hier ein Beispiel mehr oder weniger aus dem Saks Artikel gehoben:

#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; 
} 

Wenn die Funktion Erklärung abgegeben wird sichtbar, ändert sich das Verhalten des Programms im Hintergrund, da zwischen der Funktion foo und der cla kein Namenskonflikt besteht ss foo.

Wenn Sie jedoch eine "typedef class foo foo;" einschließen, erhalten Sie einen Kompilierzeitfehler anstelle eines stillen Unterschieds im Verhalten.

+0

Sie müssen dies tun Viele Dinge, die dazu führen, dass ich versucht bin zu sagen, du verdienst es! Nummer eins würde Umwandlungscasts anstelle von benannten Funktionen bereitstellen (immer ein No-No, IMHO). –

+2

Konvertierungsoperatoren sind möglicherweise ein No-No, aber sie sind überhaupt nicht ungewöhnlich. Jedenfalls werde ich nicht argumentieren, dass so viele Dinge schief gehen müssen. Wie ich schon sagte, es ist nicht etwas, auf das ich in meinem oder einem anderen Code bestehe. Aber ich wollte erklären, warum es im OP-Code ist (das war die Frage immerhin), und darauf hinweisen, dass der Typedef keine Kosten verursacht und keine Probleme verursacht. In der Tat, es macht Compiler ein bisschen mehr wie die Leute erwarten - obwohl ich durch das Verhalten einiger Compiler zu Adams Schnipsel überrascht war. Ich denke, das Dokument, das von litb verlinkt wird, ist in dieser Hinsicht lehrreich. –

+0

Das ist wirklich interessant; Die Antworten, die ich auf diese Frage bekommen habe, machen mich froh, dass ich diese Frage hier gestellt habe. –

0

Es sieht aus wie der Kommentar versucht zu sagen, dass der typedef das Symbol SomeClass global in einer Weise macht, die verhindert, dass jemand ein lokales Objekt mit demselben Namen deklarieren kann, das die ursprüngliche SomeClass verbirgt.

Ich versuchte dies mit VC6 (kein echter C++ - Compiler, den ich kenne, aber das Beste, was ich ATM habe), und es scheint nicht viel zu tun. SomeClass wird immer noch durch eine lokale Deklaration mit demselben Namen versteckt. Vielleicht ändert es den Inhalt einer Fehlermeldung für einige Compiler, um es nützlicher zu machen.

-2

Ich verstehe das Konzept der verschiedenen Namespaces, die Tags und Identifikatoren leben, aber das ist wirklich sogar die Mühe wert eingeben?

Nr

+6

(-1) Absolut keine Erklärung oder Argumentation. Ich hätte genauso gut "Ja" schreiben können. und der einzige Unterschied wäre Ruf gewesen. – DevinB

+0

Sie mögen meine Antwort nicht (er hat schließlich die Gründe dargelegt), schreiben Sie Ihre eigene. –

0

Es sieht für mich wie Ihr Kollege nicht vollständig von C. absolviert haben kann

In C, wenn Sie struct foo {int a;}; erklären, Sie haben nichts können Sie rufen Sie einfach foo , aber eher struct foo. Daher ist es ziemlich üblich, def struct foo als foo einzugeben.

Dies wurde in C++ geändert, aus Gründen, die ziemlich offensichtlich sein sollten.

+1

Es ist möglich, aber ich würde nicht wirklich C Verhalten nennen "Namen zu verstecken." –

20

Es verhindert, dass Code wie folgt kompilieren:

class SomeClass { ... }; 
int SomeClass; 

Dies ist völlig legal C++, obwohl es schrecklich ist. Wenn Sie dies tun, beziehen sich alle Verweise auf ein blankes SomeClass auf die Variable. Um auf die Klasse zu verweisen, müssen Sie bei jeder Verwendung explizit class SomeClass angeben. Wenn Sie eine typedef erstellen:

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

Dann wird der Compiler-Flags, die Definition von int SomeClass als Fehler, wie es sollte richtig sein.

+0

Ihr zweites Beispiel kompiliert für mich (VC2005). –

+3

Problem mit VC++ dann - es sollte nicht kompilieren. –

+0

Interessant, es funktioniert tatsächlich mit einem Compiler, den ich benutze (und nicht mit MSVC) – Dolphin

0

Entweder wirklich kaputt Compiler oder jemand nicht wissen, was sie tun, oder so würde ich denken.

+0

Oder jemand, der etwas weiß, was viele Leute nicht wissen ... –

6

Adam hat den richtigen Grund dafür angegeben, aber in Bezug auf Ihre Frage "Ist es die Mühe wert" würde ich ein klares "Nein!" Geben.Der mögliche Problemcode:

class SomeClass { ... }; 
int SomeClass; 

wird gefangen werden, wenn ein bisschen später jemand sagt:

SomeClass sc; 

Zugegeben der Compiler auf der „falschen“ Linie zeigen, aber diese Art der Sache geschieht so selten (Ich glaube nicht, dass ich es jemals in echtem Code gesehen habe), dass es keinen Wald von fast überflüssigen Typedefs rechtfertigen kann.

+0

Danke, dass du diese Frage beantwortet hast, das wollte ich wirklich wissen. Ich hatte es noch nie zuvor gesehen, also hatte ich das Gefühl, dass es das nicht wert wäre. –

+0

Wenn Sie die Typedef weglassen, erhalten Sie möglicherweise nicht immer einen Fehler, obwohl die Situationen zugegebenermaßen selten sind. Eine Funktion mit demselben Namen wie eine Klasse kann etwas verbergen, das sonst ein Klassenkonstruktor wäre. –

+0

Könnten Sie ein Beispiel dafür schreiben - ich kann mir nicht vorstellen, wie es möglich wäre. –