44 votes

Avantages et inconvénients de l'utilisation de classes et d'énumérations imbriquées C ++?

Quels sont les avantages et les inconvénients de l'utilisation de imbriquée public des classes C++ et les énumérations? Par exemple, supposons que vous avez une classe appelée printer, et cette classe stocke également des informations sur des bacs de sortie, vous pourriez avoir:

class printer
{
public:
    std::string name_;

    enum TYPE
    {
        TYPE_LOCAL,
        TYPE_NETWORK,
    };

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

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

Sinon:

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;

Je peux voir les avantages de nidification privé enums/classes, mais quand il s'agit de celles du public, le bureau est divisé - il semble être plus un choix de style.

Alors, laquelle préférez-vous et pourquoi?

44voto

paercebal Points 38526

Classes imbriquées

Il ya plusieurs effets secondaires des classes imbriquées à l'intérieur des classes que j'ai l'habitude de considérer les défauts (si ce n'est de la pure antipatterns).

Imaginons le code suivant :

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

   // etc.
} ;

Ou encore:

class A
{
   public :
      class B ;

   // etc.
} ;

class A::B
{
   public :

   // etc.
} ;

Donc:

  • Privilégiées d'Accès: A::B a privilégiées d'accès à tous les membres d'Une (méthodes, les variables, les symboles, etc.), ce qui affaiblit l'encapsulation
  • Un champ est candidat à la recherche de symbole: code de l'intérieur de B voir tous les symboles à partir d'Une comme des candidats possibles pour une recherche de symbole, qui peut confondre le code
  • l'avant-déclaration: Il n'y a aucun moyen de l'avant-déclarer Un::B sans donner l'intégralité de la déclaration d'Un
  • Extensibilité: Il est impossible d'ajouter une autre classe A::C, sauf si vous êtes propriétaire d'Un
  • Code de verbosité: mettre les classes en classes rend seulement les en-têtes de plus. Vous pouvez toujours séparés en plusieurs déclarations, mais il n'y a pas moyen d'utiliser l'espace de noms comme alias, les importations ou de l'usage.

En conclusion, sauf exceptions (par exemple, la classe imbriquée est une partie intime de l'imbrication de la classe... Et puis même...), je ne vois pas en classes imbriquées dans le code, comme les lacunes outweights par les magnitudes les avantages perçus.

En outre, il sent comme une tentative maladroite pour simuler namespacing sans l'aide de C++ espaces de noms.

Sur le pro-côté, vous isoler de ce code, et si privé, de le rendre inutilisable, mais de "l'extérieur" de la classe...

Imbriqués les énumérations

Avantages: Tout.

Con: Rien.

Le fait est enum éléments vont polluer la portée mondiale:

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

// empty is from Value or Glass?

Ony en mettant chaque enum dans un espace de noms différent/classe vous permettra d'éviter cette collision:

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 ;

A noter que C++0x défini la classe enum:

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

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

exactement pour ce genre de problèmes.

6voto

Adam Rosenfield Points 176408

Un inconvénient qui peut devenir un gros problème pour les grands projets est qu’il est impossible de faire une déclaration directe pour les classes ou les énumérations imbriquées.

2voto

Paul Nathan Points 22910

Si vous n'utilisez jamais la classe dépendante pour autre chose que de travailler avec les implémentations de la classe indépendante, les classes imbriquées conviennent, à mon avis.

C'est quand vous voulez utiliser la classe "interne" comme un objet à part entière que les choses peuvent commencer à devenir un peu manky et que vous devez commencer à écrire des routines d'extraction / insertion. Pas une belle situation.

2voto

carson Points 3852

Il semble que vous devriez utiliser des espaces de noms plutôt que des classes pour regrouper les éléments liés les uns aux autres. Un inconvénient que j'ai pu constater en faisant des classes imbriquées est que vous vous retrouvez avec un fichier source très volumineux qui pourrait être difficile à assimiler lorsque vous recherchez une section.

1voto

Nick Points 5293

paercebal dit tout ce que je dirais à propos de imbriqués les énumérations.

WRT classes imbriquées, ma commune et presque seul cas d'utilisation pour eux, c'est quand j'ai une classe qui est de la manipulation d'un type particulier de ressource, et j'ai besoin d'une classe de données qui représente quelque chose de spécifique à cette ressource. Dans votre cas, output_tray pourrait être un bon exemple, mais je n'ai généralement pas de classes imbriquées si la classe va avoir toutes les méthodes qui vont être appelés à partir de l'extérieur de la classe conteneur, ou est plus que principalement une classe de données. J'en général ne font pas de nid classes de données, à moins que le contenu de la classe n'est pas toujours directement référencé à l'extérieur de la classe conteneur.

Ainsi, par exemple, si j'avais un printer_manipulator classe, il pourrait avoir un contenu de classe pour imprimante erreurs de manipulation, mais l'imprimante elle-même serait un non-contenu de la classe.

Espérons que cette aide. :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X