テンプレートファクトリオブジェクト(再び、および15行)

画像



こんにちは



私はC ++を初めて使用しますが、一般的には自分の喜びのためだけに(そして時々エキゾチックなプラットフォームのために)プログラムします。理論的な本を読んでいません。執筆プロセスでGoogle、Stack Overflow、直感を積極的に使用しています。



これにより質問の一部が削除され、驚きの外観が防止されることを願っています。 :)



それでも、空き時間に次の自転車を(プラスとQtオームで)書いた後、この場所に何らかのメカニズムをねじ込むといいと思いました。 さらに、私が理解しているように、 オブジェクトの抽象ファクトリーと呼ばれるより一般的なデザインパターンがあり、その本質は私がキャッチしませんでした、そしてより単純な抽象化は、オブジェクトが多くのクラス識別子のペアについて知っているということです、そしてそれは作成することができます識別子によるクラスのインスタンス(最も単純な場合、この識別子は文字列ですが、列挙などを使用すると便利です)。 私が望むもの(つまり、最後の1つ)を多少理解したとき、私は自分に合った既製の美しいソリューションを探しに登りましたが、ほとんどすべてのGoogleをレイプしましたが、驚くべきことに、それを見つけませんでした



その結果、そのようなナンセンスに許容できない時間を費やして、私は自分のユニークな場所の山から集めて(Googleの残りの部分に到達し)、まだエレガントで小さいようです(本当に小さい...私は全体の投稿の必要性さえ疑います...)バイク、テンプレートクラス、テンプレート関数、特殊化、さらにはC ++ 11の 可変テンプレート関数など、多くのことを処理する必要があります



まさに私が欲しいものを予約しましょう。 最初に、もちろん、私はルーマンキャラクターrtorstenの記事を読みました ストリーム オブジェクトを 配置し ます オブジェクトのファクトリパターンです 。しかし、起こっているすべての意味がまだ伝わっておらず、実装が少し過負荷に見え、コンストラクタに引数を渡す方法がありませんなるほど。 この投稿は、同じことをやろうとしているが、より良い試みだと言うことができます。 さて、そして次に、私が望んだことと達成したこと(それは一致したはずです:)):ベースクラスBase



とそこからの2つの直接の子孫があると仮定します: Derived1



Derived2



、ファクトリによって作成したいインスタンス。



上記はその記事でカバーされていますが、私も欲しいです

つまり、次のようなものです。
 #include <iostream> #include <string> #include "factory.h" using namespace std; class Animal{ public: Animal(bool isAlive,string name) : isAlive(isAlive),name(name){}; bool isAlive; string name; virtual string voice() const=0; }; class Dog : public Animal{ public: using Animal::Animal; string voice() const{ return this->isAlive? "Woof! I'm "+this->name+"\n": ""; } }; class Cat : public Animal{ public: using Animal::Animal; string voice() const{ return this->isAlive? "Meow, I'm "+this->name+"\n": ""; } }; int main(void){ GenericObjectFactory<string,Animal,bool,string> animalFactory; animalFactory.add<Dog>("man's friend"); animalFactory.add<Cat>("^_^"); Animal *dog1=animalFactory.get("man's friend")(true,"charlie"); Animal *dog2=animalFactory.get("man's friend")(false,"fido"); Animal *cat =animalFactory.get("^_^")(true,"begemoth"); cout << dog1->voice() << dog2->voice() << cat ->voice(); return 0; }
      
      



したがって、 animalFactory



ファクトリは、最初にanimalFactory



テンプレートクラスから作成され、そのキーパラメータはキータイプ (この例では文字列ですが、整数値や列挙など他のものを使用すると便利な場合があります)これらの値は、クラスを作成するためにファクトリに追加する必要があるクラスです。 2番目の必須パラメーターとして-これらのクラスの基本クラス(および1つのクラスから継承する必要があります); 残りの2つのパラメーター(任意の数(ゼロを含む))は、ファクトリーによって作成されたクラスのコンストラクターの引数のタイプです。



その後、テンプレートメンバ関数add



呼び出して、ファクトリにクラスを追加できます。実際には、ファクトリが登録する必要があるクラスを最初の唯一のパラメータとして、最初の唯一の引数として、このクラスの識別子、この場合は文字列(定義済みテンプレートクラスの最初のパラメーター)。



その後、楽しみが始まります。 get



メンバー関数は、識別子文字列を最初で唯一の引数として使用し、この識別子で見つかったクラスのいわゆるインスタンス生成子を返します。 Instantiatorは、(ファクトリーの特殊化中に指定された数と型の)引数のセットを受け取り、目的のクラスのインスタンスを作成してコンストラクターに渡す関数です。 必要なプロキシの一種で、その理由を説明します。 これは、コンストラクター自体が返された方法と非常に似ています。 :)同時に、インスタンシエーターは作成されたオブジェクトへのポインターを返しますが、このポインターは継承された型ではなく、 基本クラスのものです。 必要に応じて、 dynamic_cast



'threadを実行できます。



ところで、このインスタンス生成プログラムをどこかに保存することを妨げるものはありません。
 auto catInstantiator=animalFactory.get("^_^");
      
      



、必要なときに後でオブジェクトを作成します。
 Animal *cat=catInstantiator(true,"delayed cat"); Animal *cat=catInstantiator(false,"dead delayed cat");
      
      



:)

しかし、大丈夫、最終的には明らかでした。 また、私がこのメモを書いているのはベテランのプラスではなく、何らかの理由で工場を作りたいと思っている初心者向けです。 :)






ファクトリの実際の実装を見てみましょう。 作成または登録するときのファクトリー内のクラスの有無に関するすべての種類のチェック、および同様のロジックと他のあらゆる種類の便利さを含む、それが機能しないことなく意図的にすべてを切り取りました(または、QtからSTLにこれを移植するには遅すぎました)追加するのは難しくありません。 しかし、一般に、サンプルコードはできるだけシンプルで明白なものである必要があると考えています。もちろん、これらの避けられない悪魔的な詳細はありません。理解しやすく、これがまさに今必要なことです。
  1. #include <map>
  2. テンプレート < クラス ID、 クラス Base、 クラス ...引数> クラス GenericObjectFactory {
  3. プライベート
  4. typedef Base * * fInstantiator 引数... ;
  5. template < class Derived > static Base * instantiator Args ... args {
  6. 新しい Derived 引数... )を 返し ます。
  7. }
  8. std :: map < ID、fInstantiator >クラス;
  9. 公開
  10. GenericObjectFactory { }
  11. template < class Derived > void add ID id {
  12. classes [ id ] = instantiator < Derived > ;
  13. }
  14. fInstantiator get ID id {
  15. クラス[ id ]を 返します
  16. }
  17. } ;
それだけです! 象じゃない? 彼の記事で提案されたrtorstenのソリューションを少なくとも3回は超えているように思えます。



ここで何が起こっているのか:

私はC ++を初めて使用することに言及しましたか? :)だから、私はいくつかの場所に嘘をついた可能性が高い(または、たぶんいくつかの場所にいない )...



最後のリストを取得して、 #include "factory.h"



代わりに最初のリストに貼り付け、お気に入りのコンパイラで結果を確認し、 C ++ 11標準のサポートを含めることを忘れないでください。



PS一般的に、最初は工場のバージョンを最初の記事にコメントしたかったのですが、何らかの理由で私は投稿を書きました...とにかく、LANのエラーについて話し合うのは非常にうれしいです... :)



PPSああ! ただ送信したかったのですが、 イデオネがいたことを思い出しました! 例を記入しました: 感心することができます 。 :)



All Articles