2010-12-05 7 views
2

Ich konnte nichts relevantes finden, aber es tut mir leid, wenn dies bereits gefragt wurde. Ich finde mich manchmal in einer Situation wieder, in der ich eine Klasse habe, die intern zwei verschiedene Container enthält. So etwas wie das Folgende:C++: Entwerfen der Schnittstelle einer Klasse mit vielen Containern

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

Irgendwie fühle ich mich unwohl. Ist das eine kluge Art zu tun, was ich mache? Im Grunde müsste ich für jeden Container typedefs und (const overloaded) Methoden starten und beenden. Ich bin gespannt: Wie würden Sie die Schnittstelle gestalten, die Typdefinitionen benennen usw.? Ich denke, ich bin im Grunde besorgt über die Schnittstelle und die Explosion der Methoden, und es sieht auch ein bisschen hässlich aus.

Eine Möglichkeit, die Anzahl der Anfangs-/Ende-Methoden zu begrenzen, wäre ein Template-basierter Ansatz, der einige Arten von Tags verwendet, aber ich bin mir nicht sicher, ob das sinnvoll ist.

Danke!

Antwort

4

Es klingt wie Ihre Klasse zu viel tut. Wenn Ihre Clients alle diese Operationen für diese Container ausführen müssen, ist es wahrscheinlich am besten, wenn Sie nur einen konstanten Verweis auf den Container selbst bereitstellen, anstatt zu versuchen, jede STL-Schnittstelle selbst zu umbrechen.

Auf der anderen Seite, wenn Ihre Kunden all diese Dinge tun müssen, ist es wahrscheinlich ein Zeichen, dass die Klasse in kleinere Klassen aufgeteilt werden muss.

+3

Ganz im Gegenteil, würde ich sagen. Die Klasse tut nicht GENUG, wenn alle Operationen auf den Interna über passieren. Client-Code. –

+0

+1 sowohl auf die Antwort als auch auf den Kommentar: Dies sieht wie ein peinlicher Mittelweg aus, zwischen Clients zu erlauben, zu tun, was sie wollen, und einen gewissen konsistenten Zustand zwischen den Containern sicherzustellen. – suszterpatt

+0

@Noah Roberts: Das ist ein guter Punkt. –

0

Haben Sie das tatsächlich versucht? Dein Code wird nicht kompiliert. Sie können nicht zwei Funktionen mit derselben Namen/Parameter-Liste haben, die verschiedene Dinge zurückgeben.

In Bezug auf die Absicht ... Ihre Bedenken sind angemessen und Ihre Klasse wird wahrscheinlich nicht genug von seiner eigenen Arbeit tun, um ihre Existenz zu gewährleisten. Gerade die Tatsache, dass Sie die gesamten Interna des Objekts offenlegen wollen, damit Clients daran arbeiten können, lässt mich zu dem Schluss kommen, dass Ihre Klasse mit ziemlicher Sicherheit zu 100% nutzlos ist. Es ist ein Design-Problem und deine Bedenken sind einfach deine Nase, die dir sagt, dass etwas stinkt.

+0

Nun, die Methoden könnten umbenannt werden, aber trotzdem. Wo zeichnet man dann eine Linie? Der Grund für die Anfangs-/Ende-Methode war, dass es immer ein bisschen schwierig ist, die Zukunft vorherzusagen, und mir scheint es eine gute Möglichkeit zu sein, dem Klienten die Möglichkeit zu geben, zu tun, was er will. – Jay

+1

"... eine gute Möglichkeit, dem Kunden die Möglichkeit zu geben, zu tun, was er will." <- irgendwie fehlt der Punkt von OO - speziell Verkapselung - fürchte ich. –

+0

der Kunde kann immer tun, was er will. Der Sinn des Schreibens einer Bibliothek besteht darin, dem Kunden * eine bestimmte Aufgabe * zu ermöglichen, ohne sie selbst programmieren zu müssen. Wenn Sie nicht bereit sind, im Auftrag des Kunden Entscheidungen zu treffen, ist Ihre Bibliothek nutzlos. Jede Bibliothek ist eine Abstraktion, eine Vereinfachung, eine spezifische Art, ein Problem zu lösen. Wenn der Client es auf eine andere Weise gelöst hat, müssen sie eine andere Bibliothek finden. Du kannst nicht alles machen. Du wirst nichts Gutes tun. – jalf

0

Sie sollten den Zugriff auf die Container nicht zulassen. Sie sollten die Funktionalität der Klasse exportieren und die Klasse sollte einen zentralen Punkt haben. Angenommen, die Klasse verwendet die Container, z. int ist ein Schlüssel, der auf X verweist. Sie benötigen wahrscheinlich eine Schnittstelle, die den Zugriff koordiniert. In diesem Fall sollten Sie keinen Zugriff auf die zugrunde liegenden Container bereitstellen.