pimpl
takelさん(id:takel)が、循環参照になるプログラムの解決方法を教えてくれましたヽ(´ー`)ノ
//Hoge.h class Hoge{ private: Moke _moke; Hogera _hogera; Hogehoge* _pHogehoge; };
というクラスがある場合、MokeとHogeraとHogehogeを定義したヘッダファイルをincludeすることになります。ここでは、それぞれ、"Moke.h" "Hogera.h" "Hogehoge.h"とします。
ここで問題なのが、Hogehogeクラスの中で、Hogeをメンバとして置くことがあるかもしれないということです。
そうなると、HogehogeクラスはHoge.hをincludeする必要があります。
しかし、Hoge.hでは、Hogehogeをincludeしているので、循環参照になり、困ってしまいます。
自分的には、こういうことで時間を使うのはすごい嫌なので、takelさんの教えてくれた、pimplパターンを適用してみます。
//Hoge.h class Hoge{ public: Hoge(); private: class Impl; smart_ptr<Impl> _pImpl; };
//Hoge.cpp #include "Hoge.h" #include "Moke.h" #include "Hogera.h" #include "Hogehoge.h" class Hoge::Impl{ private: Moke _moke; Hogera _hogera; Hogehoge* _pHogehoge; }; Hoge::Hoge() : _pImpl(new Impl) {}
こうすれば、ヘッダファイルには、includeする必要が無くなり、循環参照で困ることが無くなります。
依存関係を気にせずに、includeできて非常に(・∀・)イイ!!ですね。
ただ、少し気になるのが、速度。
例えば、これを実装しているクラスが、CAppなどの、global変数置き場(?)などの場合、
//CApp.h class CDraw; class CSound; class CCharaList; class CApp{ public: CApp(); CDraw* getDraw(); CSound* getSound(); CCharaList* getCharaList(); private: class Impl; smart_ptr<Impl> _pImpl; };
//CApp.cpp #include "CApp.h" #include "CDraw.h" #include "CSound.h" #include "CCharaList.h" class CApp::Impl{ public: CDraw* getDraw(){ return &_draw; } CCharaList* getCharaList(){ return &_charaList; } CSound* getSound(){ return &_sound; } private: CDraw _draw; CSoound _sound; CCharaList _charaList; }; CApp::CApp() : _pImpl(new Impl) {} CDraw* CApp::getDraw(){ return _pImpl->getDraw(); } CSound* CApp::getSound(){ return _pImpl->getSound(); } CCharaList* CApp::getCharaList(){ return _pImpl->getCharaList(); }
こうやって書くことになります。
普段であれば、ヘッダに書いて、インライン展開されるはずの関数が、cppファイルに移動しているため、インライン展開が出来ません。……出来ないよね?
しかも、CAppは、最上位にあるクラスなので、あらゆるクラスから頻繁にアクセスされます。
こういう、上位にあるクラスについては、pimplパターンを適用しない方が良いかもしれないですね。
まあ、どうしても循環参照が鬱陶しくなったクラスだけ、このpimplパターンを適用してみますか……。