Klassendeklaration von eigebetteten Klassen



  • Hallo, ich habe eine Klasse mit einer eingebetteten Klasse:

    //A.hpp
    class A {
        public:
            class B {};
    };
    

    Nun hab ich eine Klasse, die beide Klassen verwendet:

    //Client.hpp
    //#ifndef und so ein Zeugs...
    
    class A;
    class A::B;
    
    class Client {
        private:
            A* a;
            B* b;
    }
    

    Das Problem hier ist, dass ich keine 'reine' Deklaration von A::B durchführen kann, weil die Definition von A benötigt wird - ich müsste also vorher #include "A.hpp" schreiben, was ich aber nach dem Konzept von Scott Meyers im Buch Effektiv C++ programmieren, Lektion 34 (Kompilationsabhängigkeiten), nicht tun sollte.

    Deshalb frage ich: Gibt es einen anderen Trick, eine Deklaration von B einzuführen ohne #include "A.hpp" zu benutzen? Ich könnte B natürlich auch aus A entfernen, aber von meinem Konzept her macht sich dir Klasse dort ganz gut.

    Im Prinzip ist class A; doch eigentlich genau das Selbe wie class A::B;, oder?



  • Hi,

    Ja das gibt es.

    Das ist das so genannte pimpl-idiom.

    Damit kannst du so ziemlich alles was in private steht verstecken.

    Ein Beispiel:

    // bsp.h
    #include <boost/shared_ptr.hpp>
    
    class Bsp
    {
     private:
      struct BspImpl;
      const boost::shared_ptr<BspImpl> pimpl;
    };
    
    // bsp.cc
    #include "bsp.h"
    #include "a.hpp"
    
    struct Bsp::BspImpl
    {
      A *foo;
      A::B *bar;
    
    };
    
    Bsp::Bsp()
     :pimpl(new Bsp::BspImpl)
    {}
    

    [Edit]
    Natürlich kannst du das auch ohne boost::shared_ptr machen, aber ich finde es besser, da man sich nicht um das löschen des Objekts kümmern muss.
    [/Edit]

    Ich hoffe das Beispiel war verständlich genug, ansonsten kann ich dich nur Auf Exceptional C++ von Herb Sutter verweisen, da ist dieses PIMPL-IDIOM beschrieben.

    MfG eViLiSSiMo



  • Der const boost::shared_ptr erlaubt aber das Kopieren, jedoch nicht das Zuweisen des Objekts... Wie wäre es mit boost::scoped_ptr? Dann muss man zwar noch einen leeren Destruktor in die .cpp schreiben, aber dafür hat man konsistente Semantiken und als theoretischen Bonus keinen Overhead.


Anmelden zum Antworten