it-swarm.com.de

Interne Typedefs in C ++ - guter oder schlechter Stil?

Etwas, das ich in letzter Zeit oft gemacht habe, ist das Deklarieren von Typedefs, die für eine bestimmte Klasse in dieser Klasse relevant sind, d. H.

class Lorem
{
    typedef boost::shared_ptr<Lorem> ptr;
    typedef std::vector<Lorem::ptr>  vector;

//
// ...
//
};

Diese Typen werden dann an anderer Stelle im Code verwendet:

Lorem::vector lorems;
Lorem::ptr    lorem( new Lorem() );

lorems.Push_back( lorem );

Gründe warum es mir gefällt:

  • Es reduziert das durch die Klassenvorlagen verursachte Rauschen, std::vector<Lorem> Wird zu Lorem::vector Usw.
  • Es dient als Absichtserklärung - im obigen Beispiel soll die Lorem-Klasse über boost::shared_ptr Referenziert und in einem Vektor gespeichert werden.
  • Dies ermöglicht eine Änderung der Implementierung - d. H., Wenn Lorem geändert werden muss, um zu einem späteren Zeitpunkt (über boost::intrusive_ptr) Eine störende Referenzzählung durchzuführen, hat dies nur minimale Auswirkungen auf den Code.
  • Ich denke, es sieht "hübscher" aus und ist wohl leichter zu lesen.

Gründe, warum es mir nicht gefällt:

  • Es gibt manchmal Probleme mit Abhängigkeiten - wenn Sie beispielsweise einen Lorem::vector - Code in eine andere Klasse einbetten möchten, Lorem aber nur weiterleiten müssen (oder möchten) (anstatt eine Abhängigkeit von seiner Header-Datei einzuführen), müssen Sie dies tun Am Ende müssen Sie die expliziten Typen verwenden (z. B. boost::shared_ptr<Lorem> anstatt Lorem::ptr), was ein wenig inkonsistent ist.
  • Es kann nicht sehr häufig sein, und daher schwerer zu verstehen?

Ich versuche, objektiv mit meinem Codierungsstil umzugehen, daher wäre es gut, ein paar andere Meinungen dazu einzuholen, damit ich mein Denken ein wenig analysieren kann.

167
Will Baker

Ich denke, es ist ein exzellenter Stil und ich benutze ihn selbst. Es ist immer am besten, den Gültigkeitsbereich von Namen so weit wie möglich einzuschränken, und die Verwendung von Klassen ist die beste Möglichkeit, dies in C++ zu tun. In der C++ Standard-Bibliothek werden beispielsweise Typedefs in Klassen häufig verwendet.

142
anon

Es dient als Absichtserklärung - im obigen Beispiel soll die Lorem-Klasse über boost :: shared_ptr referenziert und in einem Vektor gespeichert werden.

Genau das macht es nicht tun.

Wenn ich 'Foo :: Ptr' im Code sehe, habe ich absolut keine Ahnung, ob es sich um ein shared_ptr oder ein Foo * handelt (STL hat :: Zeigertypedefs, die T * sind, erinnern Sie sich) oder was auch immer. Esp. Wenn es sich um einen gemeinsam genutzten Zeiger handelt, gebe ich kein typedef an, behalte aber die Verwendung von shared_ptr explizit im Code bei.

Tatsächlich verwende ich kaum Typedefs außerhalb der Template-Metaprogrammierung.

Die STL macht so etwas die ganze Zeit

Das STL-Design mit Konzepten, die in Form von Elementfunktionen und verschachtelten Typedefs definiert sind, ist eine historische Sackgasse. Moderne Vorlagenbibliotheken verwenden kostenlose Funktionen und Merkmalklassen (vgl. Boost.Graph), da diese eingebaute Typen nicht ausschließen Das Modellieren des Konzepts und das Anpassen von Typen, die nicht unter Berücksichtigung der Konzepte der angegebenen Vorlagenbibliotheken entworfen wurden, wird dadurch einfacher.

Verwenden Sie die STL nicht als Grund, um dieselben Fehler zu machen.

13

Typedefs sind diejenigen, auf denen richtlinienbasiertes Design und Merkmale in C++ aufgebaut ist. Die Leistungsfähigkeit der generischen Programmierung in C++ beruht also auf Typedefs.

9
Özgür

Typdefs sind definitiv ein guter Stil. Und alle deine "Gründe, die ich mag" sind gut und richtig.

Über Probleme hast du damit. Nun, die Vorwärtserklärung ist kein heiliger Gral. Sie können einfach Ihren Code entwerfen, um Abhängigkeiten auf mehreren Ebenen zu vermeiden.

Sie können typedef außerhalb der Klasse verschieben, aber Class :: ptr ist so viel hübscher als ClassPtr, dass ich das nicht mache. Für mich ist es wie bei Namespaces - die Dinge bleiben im Rahmen des Geltungsbereichs verbunden.

Manchmal habe ich getan

Trait<Loren>::ptr
Trait<Loren>::collection
Trait<Loren>::map

Dies kann für alle Domänenklassen und mit einer gewissen Spezialisierung für bestimmte Domänenklassen Standard sein.

8
Mykola Golubyev

Ein weiteres Votum dafür ist eine gute Idee. Ich habe damit angefangen, als ich eine Simulation geschrieben habe, die sowohl zeitlich als auch räumlich effizient sein musste. Alle Werttypen hatten einen Ptr-Typ, der als gemeinsamer Boost-Zeiger begann. Ich habe dann einige Profile erstellt und einige in einen aufdringlichen Boost-Zeiger geändert, ohne den Code ändern zu müssen, in dem diese Objekte verwendet wurden.

Beachten Sie, dass dies nur funktioniert, wenn Sie wissen, wo die Klassen verwendet werden, und dass für alle Verwendungen dieselben Anforderungen gelten. Ich würde dies beispielsweise nicht im Bibliothekscode verwenden, da Sie beim Schreiben der Bibliothek nicht wissen können, in welchem ​​Kontext sie verwendet wird.

3
KeithB

Die STL macht so etwas die ganze Zeit - die typedefs sind Teil der Schnittstelle für viele Klassen in der STL.

reference
iterator
size_type
value_type
etc...

sind alle typedefs, die Teil der Schnittstelle für verschiedene STL-Vorlagenklassen sind.

3
Michael Burr

Derzeit arbeite ich an Code, der diese Art von Typedefs intensiv verwendet. Soweit ist das in Ordnung.

Aber mir ist aufgefallen, dass es häufig iterative typedefs gibt, die Definitionen auf mehrere Klassen verteilt sind und man nie wirklich weiß, mit welchem ​​Typ man es zu tun hat. Meine Aufgabe ist es, die Größe einiger komplexer Datenstrukturen, die sich hinter diesen Typedefs verbergen, zusammenzufassen. Daher kann ich mich nicht auf vorhandene Schnittstellen verlassen. In Kombination mit drei bis sechs Ebenen verschachtelter Namespaces wird es dann verwirrend.

Bevor Sie sie verwenden, müssen einige Punkte beachtet werden

  • Braucht noch jemand diese Typedefs? Wird die Klasse häufig von anderen Klassen verwendet?
  • Verkürze ich die Verwendung oder verstecke ich die Klasse? (Wenn Sie sich verstecken, können Sie auch an Schnittstellen denken.)
  • Arbeiten andere Leute mit dem Code? Wie machen Sie das? Finden sie es einfacher oder werden sie verwirrt?
2
Bodo

Ich empfehle, diese Typedefs außerhalb der Klasse zu verschieben. Auf diese Weise entfernen Sie die direkte Abhängigkeit von gemeinsam genutzten Zeiger- und Vektorklassen und können diese nur bei Bedarf einbeziehen. Sofern Sie diese Typen nicht in Ihrer Klassenimplementierung verwenden, sollten sie meines Erachtens keine inneren Typedefs sein.

Die Gründe, die Ihnen gefallen, stimmen noch immer überein, da sie durch das Typ-Aliasing mit typedef und nicht durch die Deklaration in Ihrer Klasse gelöst werden.

1

Wenn das typedef nur innerhalb der Klasse selbst verwendet wird (d. H. Als privat deklariert wird), halte ich es für eine gute Idee. Aus genau den Gründen, die Sie angeben, würde ich es jedoch nicht verwenden, wenn die Typedefs außerhalb der Klasse bekannt sein müssen. In diesem Fall empfehle ich, sie außerhalb der Klasse zu verschieben.

0