Frage

Was sind die Vor- und Nachteile des verschachtelten öffentliche C ++ Klassen und Aufzählungen verwenden? Angenommen, Sie haben eine Klasse namens printer, und diese Klasse speichert auch Informationen über die Ausgabefächer, könnten Sie haben:

class printer
{
public:
    std::string name_;

    enum TYPE
    {
        TYPE_LOCAL,
        TYPE_NETWORK,
    };

    class output_tray
    {
        ...
    };
    ...
};

printer prn;
printer::TYPE type;
printer::output_tray tray;

Alternativ:

class printer
{
public:
    std::string name_;
    ...
};

enum PRINTER_TYPE
{
    PRINTER_TYPE_LOCAL,
    PRINTER_TYPE_NETWORK,
};

class output_tray
{
    ...
};

printer prn;
PRINTER_TYPE type;
output_tray tray;

kann ich die Vorteile der Verschachtelung privater Aufzählungen / Klassen zu sehen, aber wenn es um öffentlich diejenigen geht, ist das Büro Split - es eher eine Art Wahl zu sein scheint,

.

Also, was tun Sie bevorzugen und warum?

War es hilfreich?

Lösung

Verschachtelte Klassen

Es gibt mehrere Nebenwirkungen Klassen innerhalb von Klassen verschachtelt, die ich in der Regel Fehler betrachten (wenn nicht reine Antipatterns).

Lassen Sie uns den folgenden Code vor:

class A
{
   public :
      class B { /* etc. */ } ;

   // etc.
} ;

Oder auch:

class A
{
   public :
      class B ;

   // etc.
} ;

class A::B
{
   public :

   // etc.
} ;

So:

  • Privilegied Zugang: A :: B hat privilegied Zugriff auf alle Mitglieder einer (Methoden, Variablen, Symbole usw.), die Verkapselung schwächt
  • Ein Anwendungsbereich ist Kandidat für die Symbol-Lookup: Code von innen B sehen alle Symbole von A als möglichen Kandidaten für ein Symbol Lookup, die den Code verwirren
  • zukunfts Erklärung: Es gibt keinen Weg A :: B zu zukunfts erklären ist eine vollständige Erklärung von A ohne Angabe
  • Extensibility: Es ist unmöglich, eine andere Klasse A :: C hinzufügen, wenn Sie Inhaber von A
  • Code-Ausführlichkeit: Klassen in Klassen setzen nur macht Header größer. Sie können dies noch getrennt in mehrere Erklärungen, aber es gibt keine Möglichkeit, Namespace-like-Aliase, die Einfuhr oder die usings zu verwenden.

Als Schlussfolgerung, es sei denn, Ausnahmen (zB die verschachtelte Klasse ist ein intimer Teil der Verschachtelung Klasse ... Und selbst dann ...), habe ich keinen Punkt in verschachtelten Klassen in normalen Code zu sehen, wie die Mängel outweights von Größen die wahrgenommenen Vorteile.

Außerdem riecht es als ein ungeschickter Versuch Namespacing zu simulieren, ohne C ++ Namespaces verwendet wird.

Auf der Pro-Seite, isolieren Sie den Code, und privat, wenn, unbrauchbar machen, sondern von „außen“ Klasse ...

Verschachtelte Aufzählungen

Pros:. Alles

Con. Nichts

Die Tatsache ist Enum Elemente werden den globalen Bereich verschmutzen:

// collision
enum Value { empty = 7, undefined, defined } ;
enum Glass { empty = 42, half, full } ;

// empty is from Value or Glass?

Ony, indem jeder ENUM in einem anderen Namespace setzen / Klasse ermöglicht es Ihnen, diese Kollision zu vermeiden:

namespace Value { enum type { empty = 7, undefined, defined } ; }
namespace Glass { enum type { empty = 42, half, full } ; }

// Value::type e = Value::empty ;
// Glass::type f = Glass::empty ;

Beachten Sie, dass C ++ 0x die Klasse Enum definiert:

enum class Value { empty, undefined, defined } ;
enum class Glass { empty, half, full } ;

// Value e = Value::empty ;
// Glass f = Glass::empty ;

genau für diese Art von Problemen.

Andere Tipps

Eine con, die eine große Sache für große Projekte werden können, ist, dass es unmöglich ist, eine Vorwärts-Deklaration für verschachtelte Klassen oder Aufzählungen zu machen.

Wenn du gehst nie die abhängige Klasse für alles zu verwenden, aber mit der unabhängigen Klasse Implementierungen arbeitet, sind verschachtelte Klassen gut, meiner Meinung nach.

Es ist, wenn Sie wollen in ihrem eigenen Recht, die „interne“ Klasse als ein Objekt zu verwenden, die Dinge beginnen, können ein wenig manky bekommen und Sie müssen beginnen Abzieh / Inserter-Routinen zu schreiben. Keine schöne Lage.

Es scheint, wie Sie Namespaces anstelle von Klassen zu gruppieren, wie Dinge verwendet werden sollen, die miteinander auf diese Weise verbunden sind. Eine con, die ich dabei verschachtelte Klassen sehen konnte, ist, dass Sie mit einer wirklich großen Quelldatei am Ende, die schwer sein könnten grok, wenn Sie für einen Abschnitt suchen.

Es gibt keine Vor-und Nachteile per se von verschachtelten öffentlichen C ++ Klassen. Es gibt nur Fakten. Diese Tatsachen werden von der C ++ Standard vorgeschrieben. Ob eine Tatsache zu geschachtelten öffentlichen C ++ Klassen ist ein Profi oder ein con hängt von dem jeweiligen Problem, das Sie versuchen zu lösen. Das Beispiel, das Sie gegeben haben kein Urteil darüber erlauben, ob verschachtelte Klassen geeignet sind oder nicht.

Eine Tatsache, über verschachtelte Klassen ist, dass sie einen privilegierten Zugang zu allen Mitgliedern der Klasse, die sie gehören. Dies ist ein con, wenn die verschachtelten Klassen nicht einen solchen Zugang benötigen. Aber wenn die verschachtelte Klasse nicht so Zugriff benötigt, dann sollte es nicht als verschachtelte Klasse deklariert wurde. Es gibt Situationen, wenn eine Klasse A will einen privilegierten Zugang zu bestimmten anderen Klassen gewähren B . Es gibt drei Lösungen für dieses Problem

  1. Erstellen B ein Freund von A
  2. Erstellen B eine verschachtelte Klasse von A
  3. Nehmen Sie die Methoden und Attribute, die B Bedarf, öffentliche Mitglieder von A .

In dieser Situation ist es # 3, die Kapselung verletzt, weil A Kontrolle über seine Freunde und über seine verschachtelte Klassen, aber nicht über Klassen, die seine öffentlichen Methoden aufrufen oder Zugriff auf seine öffentliche Attribute.

Eine weitere Tatsache über verschachtelte Klassen ist, dass es unmöglich ist, eine andere Klasse A :: C als verschachtelte Klasse von A hinzuzufügen, es sei denn, Sie sind Eigentümer von A . Dies ist jedoch durchaus sinnvoll, weil verschachtelte Klassen privilegierten Zugang haben. Wenn es möglich wäre hinzuzufügen A :: C als verschachtelte Klasse von A , dann A :: C könnte Trick A in dem Zugang zu privilegierten Informationen gewähren; und dass Yould verletzt Kapselung. Es ist im Grunde das gleiche wie bei der friend Erklärung: die friend Erklärung Sie besondere Privilegien nicht gewähren, dass Ihr Freund von anderen versteckt; es ermöglicht Ihre Freunde auf Informationen zuzugreifen, die Sie von Ihrem Nicht-Freunde verstecken. In C ++ ist ein altruistischer Akt jemand einen Freund anrufen, kein egoistischer ein. Das gleiche gilt für das Erlauben einer Klasse eine verschachtelte Klasse zu sein.

Som weitere nützliche Informationen über verschachtelte öffentliche Klassen:

  • Ein Anwendungsbereich ist Kandidat für die Symbol-Lookup von B : Wenn Sie das nicht wollen, machen B ein Freund von A statt eine verschachtelte Klasse. Es gibt jedoch Fälle, in denen Sie genau diese Art von Symbol Lookup wollen.
  • A :: B kann nicht die Zukunft gerichteten Begriffen erklärt : A und A :: B sind eng gekoppelt. In der Lage zu verwenden A :: B , ohne zu wissen A würde diese Tatsache nur verstecken.

Um dies zu fassen: Wenn das Werkzeug nicht Ihre Bedürfnisse paßt, nicht das Werkzeug der Schuld; Schuld selbst das Werkzeug für die Anwendung; andere könnten verschiedene Probleme haben, für die das Werkzeug perfekt ist.

paercebal alles gesagt, was ich über verschachtelte Aufzählungen sagen würde.

WRT verschachtelten Klassen, meint häufig und fast einziger Anwendungsfall für sie ist, wenn ich eine Klasse, die eine bestimmte Art von Ressource manipuliert, und ich brauche eine Datenklasse, die etwas Bestimmtes zu dieser Ressource darstellt. In Ihrem Fall könnte output_tray ein gutes Beispiel sein, aber ich im Allgemeinen nicht verschachtelte Klassen verwenden, wenn die Klasse alle Methoden haben wird, die von außerhalb der enthaltenden Klasse genannt werden werden, oder sind mehr als in erster Linie einer Datenklasse. Ich in der Regel tun, auch nicht verschachtelt Datenklassen, es sei denn die darin enthaltenen Klasse nicht immer direkt verwiesen außerhalb der enthaltenden Klasse ist.

So zum Beispiel, wenn ich eine printer_manipulator Klasse habe, könnte es eine enthaltenes Klasse für Fehler Drucker Manipulation, aber Drucker selbst würde eine nicht geschlossene Klasse sein.

Hoffe, das hilft. :)

Denken Sie daran, dass Sie immer eine verschachtelte Klasse zu einem Top-Level eines später fördern, aber Sie können das Gegenteil zu tun, ohne zu brechen vorhandenen Code nicht in der Lage sein. Daher wäre mein Rat es eine verschachtelte Klasse zuerst machen, und wenn es ein Problem zu werden beginnt, ist es eine Top-Level-Klasse in der nächsten Version machen.

Für mich eine große con es draußen ist, dass es Teil des globalen Namensraum wird. Wenn die ENUM oder verwandte Klasse nur dann wirklich auf die Klasse gilt, dass es in ist, dann macht es Sinn. So in dem Druckergehäuse, alles, was den Drucker vollen Zugang zu dem mit dem Enum PRINTER_TYPE wissen beinhaltet, wo sie nicht wirklich brauchen, um über sie wissen. Ich kann nicht sagen, dass ich jemals eine interne Klasse verwendet, sondern auch für eine Enumeration, dies erscheint logischer es im Innern zu halten. Als ein weiteres Plakat hat darauf hingewiesen, es ist auch eine gute Idee, um Namespaces Gruppe ähnlicher Elemente zu verwenden, da den globalen Namensraum verstopfen wirklich eine schlechte Sache sein kann. Ich habe früher an Projekten gearbeitet, die massiv sind und nur eine Auto komplette Liste auf dem globalen Namensraum dauert 20 Minuten Erziehung. Meiner Meinung nach verschachtelt Aufzählungen und Klassen Namespace / structs ist wahrscheinlich der sauberste Ansatz.

Ich akzeptiere die Beiträge für die Einbettung Ihre Enum in einer Klasse befürworten, aber es gibt Fälle, in denen es mehr Sinn macht, dass nicht zu tun (aber bitte, zumindest legt es in einem Namespace). Wenn mehrere Klassen eine ENUM sind unter Verwendung innerhalb einer anderen Klasse definiert ist, dann sind diese Klassen direkt abhängig von der anderen konkreten Klasse (dh besitzt die Enumeration). Das stellt sicher einen Designfehler, da diese Klasse für die ENUM sowie andere Aufgaben zuständig sein wird.

Also, ja, bettet die Enum in einer Klasse, wenn nur anderer Code verwendet, dass Enum mit dieser konkreten Klasse direkt zu verbinden. Ansonsten einen besseren Platz finden, die Enum wie ein Namensraum zu halten.

Wenn Sie die Enum in eine Klasse oder einen Namespace setzen, wird Intellisense können Sie Anleitung geben, wenn Sie versuchen, die Enum-Namen zu erinnern. Eine kleine Sache sicher, aber manchmal die kleinen Dinge wichtig sind.

Visual Studio 2008 scheint nicht in der Lage zu sein, Intellisense für verschachtelte Klassen zur Verfügung zu stellen, so dass ich in den meisten Fällen auf das PIMPL Idiom geschaltet, wo ich verwenden, um eine verschachtelte Klasse zu haben. Ich habe Aufzählungen immer entweder in der Klasse, wenn sie nur von dieser Klasse verwendet wird, oder außerhalb der Klasse im gleichen Namensraum wie die Klasse, wenn mehr als eine Klasse der Enum verwendet.

ich ein con für verschachtelte Klassen sehen kann, besser, dass eine generische Programmierung verwenden.

Wenn die kleine Klasse außerhalb der Big One definiert ist, können Sie die große Klasse eine Klassenvorlage erstellen und verwenden all „kleine“ Klasse, die Sie in der Zukunft mit der großen Klasse benötigen.

Allgemeine Programmierung ist ein leistungsfähiges Werkzeug, und, meiner Meinung nach, haben wir es im Auge behalten sollte, wenn erweiterbare Programme zu entwickeln. Seltsam, dass niemand diesen Punkt erwähnt hat.

Die einzige Problem mit verschachtelten Klassen, die ich in noch gestoßen war, dass C ++ nicht, uns auf das Objekt der umgebenden Klasse, in den verschachtelten Klasse Funktionen beziehen sich lassen. Wir können nicht sagen, "diese Enclosing ::"

(Aber vielleicht ist es eine Möglichkeit?)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top