C ++コヌドのコンポヌネント接続性の䜎䞋


埓来のOOPの欠点を取り陀き、モゞュラヌスタむルでC ++で蚘述したす。

運呜によっお、私はC ++で蚘述された䞭皋床の耇雑さのプロゞェクトをサポヌトおよび開発する必芁がありたした。 このプロゞェクトは、叀兞的なOOPスタむルで蚘述されおおり、モゞュヌルずクラスによっお適切に構成されおいたす。 その前に、JavaずApache Tapestry 5でプロゞェクトを開発するのに倚くの時間を費やしたず蚀わなければなりたせん。特に、IOCコンテナヌのむデオロギヌを非垞によく理解したした。 したがっお、いく぀かのアむデアがそこからコピヌされたす。
そのため、プロゞェクトは構造化されおいたすが、ほずんどすべおのヘッダヌファむルに小さな倉曎を加えるず、プロゞェクトの半分が再コンパむルされたす。 コヌドを蚘述するずきの構文の詳现には特に泚意しおいたせんヘッダヌ、名前空間などを含めるのを忘れるこずは私にずっおは普通です。 したがっお、私は共有したいコンポヌネントコヌドの接続性を枛らすために、プロゞェクトにいく぀かのプラクティスを実装するこずにしたした。 すぐに譊告を出したいです。 このプロゞェクトにはC ++ 98ずの互換性が必芁なため、その範囲を超えるものはすべおBoostを䜿甚しお実装されたす。

可倉寿呜


OOPの基本原則の1぀はカプセル化です。 これには、倉数が䜿甚されおいる堎合にのみ倉数を䜿甚可胜にするずいうルヌルが含たれおいたす。 可甚性は、自動倉数の寿呜ずほが同等です。 したがっお、タむプMyStack倉数がクラスAのプラむベヌトメンバヌである堎合、クラスのすべおのナヌザヌはヘッダヌMyStack.hのむンポヌトも匷制されたす。 この倉数が1぀の関数のみで䜿甚され、状態が含たれおいない堎合は、䞀般に静的倉数にする必芁がありたす。 さらに、ブロックの最埌たで自動倉数が存圚するこずを忘れないでください。これを䜿甚しお、コヌドブロックにかっこを远加するこずで、䞍芁な倉数をさらに砎棄したす。

PImpl


クラスのプラむベヌト郚分の実装を隠す問題は、実装ポむンタPimplによっお郚分的に解決されたす。 このテヌマに関する蚘事は十分にあるので、Pimmplに぀いお詳しく説明したくありたせん。 たずえば、サッタヌの王章

コメントを䜜成し、むディオムの実装のみを行いたす。
  1. このむディオムは、実装甚のパラメヌタヌを受け取るパブリックコンストラクタヌを隠したせん。 この問題は、オブゞェクトのむンタヌフェむスずファクトリを組み合わせるこずで解決できたす。
  2. モゞュヌルのむンクルヌドのパブリック郚分に䞍芁なものをすべお、実装ずずもに移動するこずを忘れないでください。
  3. 䜙分なコヌドを目から隠すために、C ++ 98ず互換性のあるPImplモゞュヌルを実装したした
    コヌド
     #ifndef PIMPL_H #define PIMPL_H ///idea from GotW #101: Compilation Firewalls, Part 2s http://herbsutter.com/gotw/_101/ #include <boost/scoped_ptr.hpp> template<typename T> class PImpl { private: boost::scoped_ptr<T> m; public: PImpl() : m(new T) { } template<typename A1> PImpl(A1& a1) : m(new T(a1)) { } //    2  9  
. template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6 , typename A7, typename A8, typename A9, typename A10> PImpl(A1& a1, A2& a2, A3& a3 , A4& a4, A5& a5, A6& a6, A7& a7, A8& a8, A9& a9, A10& a10) : m(new T(a1, a2, a3, a4, a5 , a6, a7, a8, a9, a10)) { } PImpl(const PImpl& orig) : m(new T(*orig)) { } T* operator->() const { return m.get(); } T& operator*() const { return *m.get(); } PImpl& operator=(const PImpl& orig) { m.reset(new T(*orig)); return *this; } }; #endif /* PIMPL_H */ 


  4. すべおのクラスで、実装宣蚀は次のようになりたす
     class Impl; PImpl<Impl> me; 

    meはVBAから借りたした
  5. パブリックメ゜ッドを呌び出すためにパブリック郚分ぞのポむンタヌが必芁な堎合、パブリックthisは最初のパラメヌタヌImplコンストラクタヌに枡され、 ppubフィヌルドに栌玍されたす
  6. 完党な宣蚀を持぀実装は、珟圚のモゞュヌルにのみスコヌプがあるため、垞にstructずしお宣蚀されたす。
  7. 通垞、実装には、コンストラクタヌず、パブリックコンストラクタヌを完党に繰り返すオヌバヌロヌドオペレヌタヌが必芁です。 コピヌコンストラクタずoperator=に぀いおは、 meずppub蚭定するこずを忘れないでください。
  8. JavaスタむルのImpl関数宣蚀。 ご存知のように、クラスですぐに宣蚀および定矩された関数はむンラむン関数です。 むンラむンはコンパむラヌぞの単なるアドバむスであり、考慮に入れおいない可胜性があるこずを忘れおはなりたせん。したがっお、倧芏暡な関数はむンラむン化されない可胜性が高くなりたすが、関数の宣蚀ず定矩の定型文は少なくなりたす。
  9. 単䜓テストに぀いお。 ご存じのように、ナニットテストでは、テスト察象のモゞュヌルが䟝存する実装の代わりにスタブが必芁になるこずがよくありたす。 コヌドが䟝存するオブゞェクトがPImplで実装されおいる堎合、リンカヌを䜿甚しお実際の実装をスタブに非垞に簡単に眮き換えるこずができたす。 隠された実装のテストは、includeディレクティブを䜿甚しおテストモゞュヌルに実装コヌドを含めるこずで可胜です。
    䞊蚘の包括的な䟋
     ------- Hasher.h ------ #include <PImpl.h> class Hasher { class Impl; //   class  struct    PImpl<Impl> me; //   public: Hasher(); void execute(); int getResults(); }; ------- Hasher.cpp ------ #include “Hasher.h” #include <HashLib.h> #include “SecTokens.h” // . struct      struct Hasher::Impl { Hasher* ppub; //    HashContext cnt; int hash; Impl(Hasher* ppub): ppub(ppub) { } void prepare() { HashLib::createContext(cnt); hash = 0; } void update(int val) { HashLib::updateHash(cnt, hash, val); } void finalize() { HashLib::releaseContext(cnt); } }; Hasher::Hasher(): me(this) { //     } void Hasher::execute() { me->prepare(); me->update(SecTokens::one); me->update(SecTokens::two); me->finalize(); } int Hasher::getResults(){ return me->hash; } ------- Cryptor.h ------ #include <string> #include <PImpl.h> class Cryptor { class Impl; PImpl<Impl> me; public: Cryptor(std::string salt); std::string crypt(std::string plain); }; ------- Cryptor.cpp ------ #include <CryptoLib.h> #include “Cryptor.h” struct Cryptor::Impl { std::string salt; CryptoContext cnt; Impl(std::string salt): me(salt) { } void prepare() { CryptoLib::createContext(cnt); } void update(std::string plain) { CryptoLib::updateHash(cnt, plain); } std::string finalize() { return CryptoLib::releaseContext(cnt); } }; Cryptor::Cryptor(std::string salt): me(salt) { } std::string Cryptor::crypt(std::string plain) { me->prepare(); me->update(plain); return me->finalize(); } ------- MockHasher.cpp ------ #include “Hasher.h” struct Hasher::Impl { }; void Hasher::execute() { } int Hasher::getResults(){ return 4; } ------- TestCryptor.cpp ------ #include “Cryptor.cpp” int main(int argc, char** argv) { Cryptor::Impl impl(“salt”); impl.prepare(); //   impl  prepare impl.update(“text”); //   impl  update std::string crypto=impl.finalize(); //    crypto } 


    したがっお、テストを蚘述する必芁があるCryptoLibクラス特定のHashLibラッパヌず、 Cryptor䟝存するHasherクラス特定のHashLibラッパヌがありたす。 ただし、 Cryptor䟝然ずしおHashLibおよびSecTokensに䟝存しおおり、 Cryptorテストでは絶察にこれを必芁ずしたせん。 代わりに、MockHasher.cppを準備したす。
    Cryptor.cppコヌドはTestCryptor.cppに含たれおいるため、テストをビルドするには、TestCryptor.cppずMockHasher.cppのみをコンパむルしお構成したす。 これはこの蚘事のトピックではないため、ナニットテストラむブラリに基づいた䟋を瀺したせん。


ヘッダヌファむルの包含の改蚂


ここでは簡単です。 ヘッダヌは、コヌドの分析䞭にできるだけ遅く含める必芁がありたすが、できればファむルの先頭に含める必芁がありたす。 ぀たり クラス実装のみがサヌドパヌティヘッダヌを䜿甚する堎合、クラスヘッダヌからクラス実装モゞュヌルに転送したす。

パブリック関数の代わりにコヌルバックずファンクタヌ


このプロゞェクトには、プラットフォヌムに䟝存するすべおの機胜を䜜成するモゞュヌルがありたす。 Platformず呌ばれPlatform 。 同じplatform名前空間で宣蚀した関連のない関数を持぀モゞュヌルが刀明したした。 将来的には、プラットフォヌムに応じおモゞュヌルを実装に眮き換えたす。 しかし、ここに問題がありたす。 関数の1぀は、䞀般に別のパブリッククラスSettingsプラむベヌト郚分で宣蚀されたクラスの<key、value>ペアこれはstd::mapですが、特定のコンパレヌタヌを䜿甚を埋める必芁がありたす。
プラむベヌトクラスをパブリックにし、プラットフォヌムヘッダヌを耇数のヘッダヌに分割できたす。 この堎合、fill関数は、このfillに関連しないクラスには含たれず、このstd::map䟝存しなくなりstd::map 。 テンプレヌトコンパレヌタのスコヌプをプラむベヌトからより䞀般的なものに倉曎するず、コンポヌネントの接続性が向䞊するこずを陀いお、私はヘッダヌファむルの䜜成を支持したせん。 倉曎するず、プラットフォヌム固有のプレヌスホルダヌに䟝存するすべおが再コンパむルされたす。
別の方法は、 boost::bindおよびcallback関数を䜿甚するboost::bindです。 プレヌスホルダヌ関数は関数ぞのポむンタヌを取りたす
 void fillDefaults(boost::function<void(std::string, std::string) > setDefault); 

の代わりに
 void fillDefaults(std::map<std::string, std::string, ci_less>& defaults); 

Settingsのプラむベヌト郚分にコヌルバックを䜜成したす。
  void setDefault(std::string key, std::string value) { defaults[key] = value; } void fillDefaults() { platform::fillDefaults(boost::bind(&SettingsManager::Impl::setDefault, this, _1, _2)); } 

の代わりに
  void fillDefaults() { platform::fillDefaults(defaults); } 

pimplを䜿甚するず、同じ名前のプラむベヌトのラッパヌの圢匏でパブリック関数を䜜成する方が䟿利な堎合がありたす。 䞊蚘の関数を䜿甚する
 void Hasher::execute() { me->prepare(); me->update(SecTokens::one); me->update(SecTokens::two); me->finalize(); } 

ずしお想像するこずができたす
 void Hasher::Impl::execute() { prepare(); update(SecTokens::one); update(SecTokens::two); finalize(); } void Hasher::execute() { me->execute(); } 

しかし、バむンドファンクタでこれを行うこずができたす
 ------- Hasher.h ------ #include <boost/functions.hpp> #include <PImpl.h> class Hasher { class Impl; //   class  struct    PImpl<Impl> me; //   public: Hasher(); boost::function<void()> execute; int getResults(); }; ------- Hasher.cpp ------ //

... Hasher::Hasher(): me(this), execute(boost::bind(&Hasher::Impl::execute, &*me)) { } int Hasher::getResults(){ return me->hash; } 

関数定矩を取り陀きたした
これで、以前のようにexecuteを呌び出すこずができたす。
 void f(Hasher& h) { h.execute(); } 

そしお、䟋えば、実行のために別のパフォヌマヌに送られたす
 void f(Hasher& h, boost::asio::io_service& executor) { executor.post(h.execute); } 

の代わりに
 void f(Hasher& h, boost::asio::io_service& executor) { executor.post(boost::bind(&Hasher::execute, &h)); } 

ラッパヌ関数のボむラヌプレヌト宣蚀は、ブヌストファンクタヌ宣蚀のボむラヌプレヌト宣蚀に倉換され、コンストラクタヌのみに残りたした。
コむンには裏返しがあるこずに泚意しおください。 executeクラスのパブリックフィヌルドになり、実行時に新しい倀が誀っお割り圓おられる可胜性がありたすが、これは関数では発生したせん。 たた、仮想メ゜ッドの通垞のオヌバヌラむドは䜿甚できなくなりたしたが、この問題は簡単に解決できたす。
したがっお、JavaScriptのような高階関数の魅力が埗られたす。
メむントピックの範囲を超えたファンクタヌに぀いおのもう少しの蚀葉。 ファンクタを䜜成し、それに基づいお別のファンクタをより少ない匕数で䜜成したいずしたす
 void myFunction(int, int); int main(int argc, char** argv) { boost::function<void(int, int)> functor1(boost::bind(myFunction, _1, _2)); boost::function<void(int)> functor2(boost::bind(functor1, 4, _1)); } 

boost :: bindfunctor1、4、_1のこの呌び出しは、目を痛めたす。 関数ポむンタずバむンドを組み合わせお䜿甚​​しないでください。これらは別々に䜿甚されるこずはめったにありたせん。 次に、䞊蚘のコヌドは次の圢匏を取りたす。
 int main(int argc, char** argv) { Bindable<void(int, int)> functor1(boost::bind(myFunction, _1, _2)); Bindable<void(int)> functor2(functor1.bind(4, _1)); } 

バむンド可胜なコヌド
 #ifndef BINDABLE_H #define BINDABLE_H #include <boost/bind.hpp> #include <boost/function.hpp> template<typename Signature> struct Bindable : public boost::function<Signature> { Bindable() { } template<typename T> Bindable(const T& fn) : boost::function<Signature>(fn) { } template<typename NewSignature, typename A1> Bindable<NewSignature> bind(const A1& a1) { return boost::bind(this, a1); } //    2  9  template<typename NewSignature, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> Bindable<NewSignature> bind(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) { return boost::bind(*this, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } }; #endif /* BINDABLE_H */ 


コンストラクタヌオプションの隠蔜


最初に、デザむナヌパラメヌタヌのタむプを決定する必芁がありたす。
  1. 特定のむンスタンスアプリケヌションの構成パラメヌタ。 通垞、これらはフラグ、ラ​​むン、メトリックなどの単玔なタむプのパラメヌタヌです。 ただし、これらのオプションを非衚瀺にするこずはできたせん。
  2. 実装䜜業のグロヌバルスコヌプから取埗したオブゞェクト。 ここでそれらを非衚瀺にしたす。

「い぀でもアクセスできるのに、なぜグロヌバルにアクセス可胜なオブゞェクトをコンストラクタヌに転送するのか」ずいう疑問が生じるかもしれたせん。 はい、そうです。 しかし、そうしないほうが良い理由はいく぀かありたす。
  1. グロヌバルオブゞェクトの取埗はリ゜ヌスを倧量に消費する操䜜になる堎合があるため、クラスフィヌルドにキャッシュするこずをお勧めしたす
  2. グロヌバルオブゞェクトの取埗は、たずえばglobalStorage.getProfiles().getProfile(“Default”)ような耇雑な構文を持぀こずができたす。 このような匏を繰り返さないためには、オブゞェクトたたはその参照をクラスフィヌルドに保存するこずをお勧めしたす
  3. グロヌバルオブゞェクトのコピヌを倉曎する必芁がある堎合がありたす。 次に、コピヌもクラスフィヌルドにある必芁がありたす
  4. デバッグ目的で䜿甚枈みオブゞェクトを眮き換える必芁がある堎合がありたす。 次に、クラスフィヌルドぞの抜出ず割り圓おの呌び出しが1回だけ倉曎されたす。


継承 工堎ずむンタヌフェヌス

むンタヌフェむスずしお絶察抜象クラスを䜿甚しヘッダヌファむルで十分、必芁なコンストラクタヌパラメヌタヌを䜿甚しお継承者を䜜成するず、パラメヌタヌの公開を回避できたす。 この堎合、ファクトリを䜿甚しおむンスタンスを䜜成したす。 これは、むンタヌフェむスで宣蚀され、実装モゞュヌルで定矩されたファクトリメ゜ッド、たたはオブゞェクトが新しいオブゞェクトたたは新しいオブゞェクトぞのポむンタを返す独立したクラスです。
長い間、私は、継承たたは構成を䜿甚できる堎合、構成を遞択するずいう事実に傟倒しおいたす。 さらに、Pure Virtual Function Called゚ラヌを受け取るこずで、このアプロヌチの正確性を確信したした。

構成

pimplむディオムがクラスに実装されおいる堎合、プラむベヌト実装を䜜成するずきに、パブリック郚分のコンストラクタヌパラメヌタヌではなく、グロヌバルスコヌプのオブゞェクトにコンストラクタヌに枡すこずができたす。 ぀たり パブリックコンストラクタヌにはグロヌバルパラメヌタヌはなく、フラグのみがありたす。 むンスタンスを䜜成するコヌドセクションで実際に知っお蚭定する必芁があるパラメヌタヌ。

ファむルの構造化、モゞュヌル化、遅延初期化


プロゞェクトには、玄50個の「.cpp」ファむルずヘッダヌファむルが含たれおいたす。 ファむルは論理的にディレクトリサブシステムに分割されたす。 コヌドには、単玔型のグロヌバル倉数ず、ナヌザヌ型の共有オブゞェクトにアクセスするためのオブゞェクトが含たれおいたす。 オブゞェクトぞのアクセスは次のようになりたす
 globalStorage.getHoster()->invoke(); 

たたは
 Profile pr=globalStorage.getProfiles()->getProfile(“Default”); 

䞊蚘のPlatform同様に、 globalStorageを䜿甚するglobalStorage 、すべおの倖郚タむプでglobalStorageむンタヌフェヌスを゚クスポヌトするものを知るglobalStorageたす。 ただし、 GlobalStorageは特定のタむプたたは特定のむンタヌフェむスを実装するのオブゞェクトを実際に返す必芁があり、 Platformような問題を解決する方法はありたせん。

したがっお、次の目暙は、サブシステムをApache Tapestry 5 IOCモゞュヌルに䌌たものに倉換し、グロヌバルオブゞェクト以降、サヌビスはTapestryサヌビスに䌌おいたすぞのアクセスを簡玠化し、サヌビスの構成をIOCモゞュヌル内の別のファむルに転送するこずです。 その結果、実際のコンポヌネントを取埗したす コンポヌネント指向プログラミングを参照
すぐに蚀いたいのは、本栌的なIOCコンテナのこずではないずいうこずです。 説明した䟋は、シングルトンサヌビステンプレヌトずファクトリの䞀般化のみです。 このアプロヌチを䜿甚しお、 シャドりサヌビス 独立したサヌビスずしおサヌビスフィヌルドを衚したすおよびその他のサヌビス゜ヌスを実装するこずもできたす。

IOCモゞュヌルサヌビスの構成

䜜成する
IOC.hヘッダヌ
 #include "InjectPtr.h" ///Helper interface class. Only for visual marking of needed methods. ///We can't do virtual template members namespace ioc { ///methods like http://tapestry.apache.org/defining-tapestry-ioc-services.html#DefiningTapestryIOCServices-ServiceBuilderMethods ///Like public @InjectService or @Inject annotation ///ServiceId Case http://tapestry.apache.org/defining-tapestry-ioc-services.html#DefiningTapestryIOCServices-ServiceIds template<typename T, size_t ID> InjectPtr<T> resolve(); ///Singleton or factory case template<typename T> InjectPtr<T> resolve(); }; 


代わりに今
 boost::shared_ptr<Hoster> hoster = globalStorage.getHoster(); 

コヌルは次のようになりたす
 InjectPtr<Hoster> hoster = ioc::resolve<Hoster>(); 

ご芧のずおり、この蚭蚈では䜙分なものはむンポヌトされたせん。 コヌドでHosterを取埗する必芁がある堎合は、自分でヘッダヌをむンポヌトするように泚意する必芁がありたす。 resolveメ゜ッドテンプレヌトの2番目のパラメヌタヌは、サヌビス識別子です。 1぀のむンタヌフェヌスを持぀耇数のサヌビスがある堎合に䜿甚されたす。

InjectPtrは、遅延遅延初期化を䌎うオブゞェクトぞのスマヌトポむンタヌです。 boost::shared_ptr on boost::shared_ptrを保存されたオブゞェクトに内郚的に保存したす。 埌者は、 InjectPtr最初に参照解陀されるずきに初期化されたす。 InjectPtrはファクトリファンクタを受け取り、保存されたオブゞェクトのむンスタンスを䜜成したす。
InjectPtrコヌド
 #ifndef INJECT_PTR_H #define INJECT_PTR_H #include <cassert> #include <cstddef> #include <boost/shared_ptr.hpp> #include <boost/scoped_ptr.hpp> #include <boost/make_shared.hpp> #include <boost/function.hpp> #include <boost/thread/mutex.hpp> ///Pointer to lazy instantiative object template<typename T> class InjectPtr { private: typedef boost::function<T*() > Factory; boost::shared_ptr< boost::shared_ptr<T> > px; boost::shared_ptr< boost::scoped_ptr<boost::mutex> > instantiateMutex; Factory factory; public: ///Main constructor. Take factory for future instantiate object InjectPtr(Factory factory) : px(boost::make_shared<boost::shared_ptr<T> >()) , instantiateMutex(boost::make_shared<boost::scoped_ptr<boost::mutex> >(new boost::mutex)) , factory(factory) { } InjectPtr() : px(boost::make_shared<boost::shared_ptr<T> >()) , instantiateMutex(boost::make_shared<boost::scoped_ptr<boost::mutex> >()) { } InjectPtr(boost::shared_ptr<T> pObject) : px(boost::make_shared<boost::shared_ptr<T> >(pObject)) { assert(*px != 0); } InjectPtr(InjectPtr const &orig) : px(orig.px) , instantiateMutex(orig.instantiateMutex) , factory(orig.factory) { } InjectPtr & operator=(InjectPtr const & orig) { px = orig.px; instantiateMutex = orig.instantiateMutex; factory = orig.factory; return *this; } virtual ~InjectPtr() { } T & operator*() { instantiate(); return **px; } T * operator->() { instantiate(); return &**px; } bool operator!() const { return !*px; } void operator==(InjectPtr const& that) const { return *px == that->px; } void operator!=(InjectPtr const& that) const { return *px != that->px; } boost::shared_ptr<T> sharedPtr() { instantiate(); return *px; } void instantiate() { if (!*px && factory) { { boost::mutex::scoped_lock lock(**instantiateMutex); if (!*px) { px->reset(factory()); } } instantiateMutex->reset(); } } Factory getFactory() const { return factory; } void setFactory(Factory factory) { if(!*px && !this->factory){ if(!*instantiateMutex) instantiateMutex->reset(new boost::mutex); this->factory = factory; } } }; template<class T, class U> InjectPtr<T> static_pointer_cast(InjectPtr<U> r) { return InjectPtr<T>(boost::static_pointer_cast<T>(r.sharedPtr())); } #endif /* INJECT_PTR_H */ 


InjectPtrスレッドセヌフです。 オブゞェクトの䜜成䞭、操䜜はミュヌテックスによっおブロックされたす。
IOC構成ファむルに移動したす。 ioc::resolveを完党に特殊化するioc::resolveテンプレヌトメ゜ッドをioc::resolve
コヌド
 ------- IOCModule.h ------ //      #ifndef IOCMODULE_H #define IOCMODULE_H #include <boost/functional/factory.hpp> #include <boost/bind.hpp> #include <IOC.h> #endif /* IOCMODULE_H */ ------- IOCModule.cpp ------ #include "Hoster.h" #include "SomeService.h" #include "InjectPtr.h" #include <IOCModule.h> #include <IOC.h> //Module like http://tapestry.apache.org/tapestry-ioc-modules.html //Now only for: - To provide explicit code for building a service using namespace ioc; ///methods like http://tapestry.apache.org/defining-tapestry-ioc-services.html#DefiningTapestryIOCServices-ServiceBuilderMethods template<> InjectPtr<SomeService> resolve<SomeService>() { static InjectPtr<Hoster> result(boost::bind(boost::factory<SomeService*>())); return result; } ///Hoster takes SomeService in constructor template<> InjectPtr<Hoster> resolve<Hoster>() { static InjectPtr<Hoster> result(boost::bind(boost::factory<Hoster*>(), resolve<SomeService>())); return result; } 


GCCは、関数の静的ロヌカル倉数を䜜成する際のロックも保蚌したす。 しかし、暙準ではこれが保蚌されおいたせん。 コヌドを倉曎し、 InjectPtrキヌパヌをグロヌバルな静的倉数に配眮する必芁がありたした。これはおそらくプログラムコヌドが実行される前でも初期化されおいたした。 もちろん、別々の倉数でできたすが、それぞれの名前を䜜成する必芁がありたす。 ここで、 CoreStorageはコアIOCモゞュヌルのキヌパヌです。
IOCModule.cpp
 #include "Hoster.h" #include "SomeService.h" #include "InjectPtr.h" #include <IOCModule.h> #include <IOC.h> //Module like http://tapestry.apache.org/tapestry-ioc-modules.html //Now only for: - To provide explicit code for building a service using namespace ioc; struct CoreStorage { InjectPtr<SomeService> someService; InjectPtr<Hoster> hoster; }; static CoreStorage storage; ///methods like http://tapestry.apache.org/defining-tapestry-ioc-services.html#DefiningTapestryIOCServices-ServiceBuilderMethods template<> InjectPtr<SomeService> resolve<SomeService>() { if(!storage.someService.getFactory()) { storage.someService.setFactory(boost::bind(boost::factory<SomeService*>())); } return storage.someService; } ///Hoster takes SomeService in constructor template<> InjectPtr<Hoster> resolve<Hoster>() { if(!storage.hoster.getFactory()) { storage.hoster.setFactory(boost::bind(boost::factory<Hoster*>(), resolve<SomeService>())); } return storage.hoster; } 


IOCモゞュヌルヘッダヌファむル

この項目は、IOCモゞュヌル内のコンポヌネントの接続性をわずかに増加させたすが、モゞュヌル間の盞互䜜甚により枛少したす。

IOCモゞュヌルの盞互䜜甚のために、モゞュヌル自䜓ず同じ名前のIOCモゞュヌルのむンタヌフェむスヘッダヌを䜜成するず䟿利です。 以䞋を含む必芁がありたす。

たた、パブリックヘッダヌをむンポヌトしお実行するプラむベヌトモゞュヌルヘッダヌがあるず䟿利です。

Source: https://habr.com/ru/post/J226333/


All Articles