2010-12-05 40 views
2

Je n'ai rien trouvé de pertinent, mais désolé si cela a déjà été demandé. Je me trouve parfois dans une situation dans laquelle j'ai une classe, qui contient intérieurement deux récipients différents. Quelque chose comme le suivant:C++: Conception de l'interface d'une classe contenant de nombreux conteneurs

class Foo 
{ 
    public: 
    typedef std::vector<int> int_list; 
    typedef std::vector<X> x_list; 

    // It would be nice if the user could iterate through these etc. so that I 
    // could define functions that operate on them as non-member non-friends. 

    typedef int_list::size_type int_list_size_type; 
    typedef int_list::const_iterator int_list_const_iter; 

    typedef x_list::size_type x_list_size_type; 
    typedef x_list::const_iterator x_list_const_iter; 

    int_list_const_iter int_list begin() const { return ints_.begin(); } 
    x_list_const_iter begin() const { return xs_.begin(); } 

    int_list::size_type size_of_ints() const { return ints_.size(); } 
    x_list::size_type size_of_xs() const { return xs_.size(); } 

    // And so forth ... ! 

    private: 
    int_list ints_; 
    x_list xs_; 
}; 

D'une certaine façon, je me sens mal à l'aise. Est-ce une façon intelligente de faire ce que je fais? Fondamentalement, pour chaque conteneur, je voudrais typedefs et (const surchargé) méthodes de début et de fin, etc Je suis curieux: quelle serait votre façon de concevoir l'interface, nommant le typedefs etc? Je suppose que je suis fondamentalement inquiet à propos de l'interface et de l'explosion des méthodes, et ça a l'air un peu moche aussi. Peut-être une façon de limiter le nombre de méthodes de début/fin serait une approche basée sur un modèle en utilisant un peu de balises, mais je ne suis pas sûr que ce soit raisonnable.

Merci!

Répondre

4

Il semble que votre classe en fasse trop. Si vos clients ont besoin de faire toutes ces opérations sur ces conteneurs, il est préférable d'exposer une référence constante au conteneur lui-même plutôt que d'essayer d'envelopper vous-même toutes les interfaces STL. D'un autre côté, si vos clients ont besoin de faire toutes ces choses, c'est probablement un signe que la classe doit être divisée en classes plus petites.

+3

Au contraire, je dirais. La classe ne fait pas ASSEZ, si toutes les opérations sur les internes se passent via. code client. –

+0

+1 à la fois à la réponse et au commentaire: cela ressemble à un terrain d'entente inconfortable entre permettre aux clients de faire ce qu'ils veulent et assurer une sorte d'état cohérent entre les conteneurs. – suszterpatt

+0

@Noah Roberts: C'est un bon point. –

0

Avez-vous réellement essayé cela? Votre code ne sera pas compilé. Vous ne pouvez pas avoir deux fonctions avec le même nom/liste de paramètres qui renvoient des choses différentes. En ce qui concerne l'intention ... vos doutes sont appropriés et votre classe ne fait probablement pas assez de son propre travail pour justifier son existence. Le fait même que vous vouliez exposer tous les éléments internes de l'objet pour que les clients puissent travailler dessus me fait conclure que votre classe est presque certainement inutile à 100%. C'est un problème de conception et vos doutes sont simplement votre nez vous disant que quelque chose pue.

+0

Eh bien les méthodes pourraient être renommées, mais de toute façon. Où est-ce qu'on trace une ligne alors? La raison pour les méthodes de début/fin était que c'est toujours un peu difficile de prédire l'avenir et pour moi cela semble être un bon moyen de donner au client la possibilité de faire ce qu'il veut. – Jay

+1

"... un bon moyen de donner au client la possibilité de faire ce qu'il veut." <- sorte de manque le point de OO - en particulier l'encapsulation - J'ai peur. –

+0

le client peut toujours faire ce qu'il veut. Le point dans l'écriture d'une bibliothèque est de permettre au client de faire * une tâche spécifique * sans avoir à le coder lui-même. Si vous n'êtes pas prêt à prendre des décisions au nom du client, votre bibliothèque est inutile. Chaque bibliothèque est une abstraction, une simplification, une manière spécifique de résoudre un problème. Si le client a besoin d'une solution différente, il devra trouver une bibliothèque différente. Tu ne peux pas tout faire. Vous finirez par ne rien faire correctement. – jalf

0

Vous ne devez pas autoriser l'accès aux conteneurs. Vous devriez exporter la fonctionnalité de la classe, et la classe devrait avoir un point central. En supposant que la classe utilise les conteneurs, par ex. int est une clé qui référence X, vous aurez probablement besoin d'une interface qui coordonne l'accès. Dans ce cas, vous ne devez pas autoriser l'accès aux conteneurs sous-jacents.