C++ 振る舞いの動的な変更

このQ&Aのポイント
  • C++で複数の処理をひとつのインターフェースでモード切り替えできる方法について
  • クラスや関数ポインタを使用して処理をまとめる方法が悩ましい
  • 名前空間を使用してstaticなメンバを持たせることも考慮している
回答を見る
  • ベストアンサー

C++ 振る舞いの動的な変更

似たような動作をする、複数の処理があるのですが、それらをひとつのインターフェースで、モード切り替えで実行できるようにしたいのですが、良い方法はありますでしょうか? 下はクラスでの例です。 class SuperClass {  virtual static void method_1() = 0;  virtual static void method_2() = 0;  ... } class classA : public SuperClass {  static void method_1() {}  static void method_2() {}  ... }; class classB : public SuperClass {  static void method_1() {}  static void method_2() {}  ... }; // 処理だけですので、メンバ変数はありません XXX::mode = A; XXX::mehod_1(); // classA のメソッドが呼ばれる。 XXX::mode = B; XXX::mehod_1(); // classB のメソッドが呼ばれる。 方法としては、クラスでも関数ポインタでも何でもかまわないんですが、 関数が複数あるため、クラスにしてまとめて変更ができると楽なのですが、 実体は特になく、static なメンバ しかないので、名前空間になるのか、、、、 どのように実装してよいか悩んでいる状態です。 よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • qwertfk
  • ベストアンサー率67% (55/81)
回答No.3

質問の意図を理解できていないのかもしれないですが、単にstatic関数をやめて通常の仮想関数にすればよいのではないでしょうか。 たとえば、実装側をこのように変更し class SuperClass { public:  virtual void method_1() = 0;  virtual void method_2() = 0; }; class classA : public SuperClass { public:  virtual void method_1() { cout << "A::method_1" << endl; }  virtual void method_2() { cout << "A::method_2" << endl; } }; class classB : public SuperClass { public:  virtual void method_1() { cout << "B::method_1" << endl; }  virtual void method_2() { cout << "B::method_2" << endl; } }; 利用側では、 auto_ptr<SuperClass> obj; obj.reset( new classA() ); obj->method_1(); // classA::method_1が呼び出される obj->method_2(); obj.reset( new classB() ); obj->method_1(); // classB::method_1が呼び出される obj->method_2(); という感じにするのが一番ではないかと思います。 どうしてもstaticクラスを使いたいなら class classA { public:  static void method_1() { cout << "A::method_1" << endl; }  static void method_2() { cout << "A::method_2" << endl; } }; class classB { public:  static void method_1() { cout << "B::method_1" << endl; }  static void method_2() { cout << "B::method_2" << endl; } }; class StaticClassCaller { public:  virtual void method_1() {};  virtual void method_2() {}; }; template<class T> class StaticClassCallerImpl : public StaticClassCaller { public:  virtual void method_1() { return T::method_1(); }  virtual void method_2() { return T::method_2(); } }; // 利用側 auto_ptr<StaticClassCaller> obj; obj.reset( new StaticClassCallerImpl<classA>() ); obj->method_1(); obj->method_2(); obj.reset( new StaticClassCallerImpl<classB>() ); obj->method_1(); obj->method_2(); とかどうでしょう。

miya_99
質問者

お礼

回答ありがとうございます。 そうですね、難しく考えずに、仮想関数で切り替えてやれば問題なさそうですね。 モードは任意数の切り替えが考えられるため、配列で管理しようと思います。 シングルトンパターンと組み合わせてやれば何とかなりそうです。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

すみません, 「virtual なメンバ関数を持つオブジェクトの配列を持つ」ではダメですね. 「virtual なメンバ関数を持つオブジェクトへのポインタの配列を持つ」にしないと, virtual の意味がないっす.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

まず「static なメンバ関数は virtual にできない」ことに注意してください. んで, やり方としてはいろいろあります. たとえば ・各関数ごとに if で切り分ける: 「アホ」といわれるかもしれない. 「どのモードでどのクラス (ないし名前空間) の関数を呼び出すか」はプログラマの責任. ・各関数ごとに「呼び出すべき関数の配列」を作っておく: 上よりはきれいになる. 「どのモードで~」は同じ. ・virtual なメンバ関数を持つオブジェクトの配列を持つ: 当然だが「オブジェクトを作ることができる」必要があるのでクラスに限定 (名前空間ではダメ). 「どの関数を呼び出すか」については統一できる. くらいは思いつく.

関連するQ&A

  • PHPでのstatic(静的)メソッド・メンバの継承について教えてください。

    次のような例にて、私の考えているように動作しません。 class ClassA {  protected static function method1()  {  echo "111";  }  public static function method2()  {  self::method1();  } } class ClassB extends ClassA {  protected static function method1()  {  echo "222";  } } ClassB::method2(); // ---> 111 と表示される。 ------ 私としては、222と表示されると予測していたのですが、 思ったように動作しません。 継承された子クラスClassBにて、method2() が実行され、 その中での self::method1(); のselfが、 ClassBではなく、親クラスのClassAを指し示していると思われます。 私としては、継承された子クラスでのselfは、相対的に、子クラスをあらわしてほしいのですが。 そういうものだ、と言われればそれまでなのですが、 これだと、self::method1(); でも、ClassA::method1(); でも同じことになってしまい、 selfの存在意義がないことになってしまうのでは?と思うのです。 私の理解のどこが間違っているのか教えていただけると幸いです。 どうぞよろしくお願いします。

    • 締切済み
    • PHP
  • [Obj-c]元クラスからサブクラスのメソッド

    Objective-Cの勉強をしています。 ClassAは元クラス(スーパークラス)です、 ClassB1、B2はClassAを継承(サブクラス)しています。 ClassAとClassB1にはiMethodというメソッドが存在します。 最下部にソースと実行結果があります。 ●そこで質問なのですが、  ClassAのインスタンスにClassB1のインスタンスをセットすると、  同じ名前のメソッドがあるだけでなぜClassB1のメソッドが呼ばれるのでしょうか?  (下記ソースの[bangai iMethod]; の部分です。)  ClassB1のインスタンスを渡すとClassAのインスタンスが  ClassB1のメソッドを使用できる理由がわかりません、  継承しているとはいえ型が違うものを参照渡しできる理由も今ひとつわからないです。  またこれはどういう機能を言うのでしょうか?  (例えば ポリモーフィズム、動的バインディングなど) ★ソース ------------------------------------------------------------------------------ #import <Foundation/Foundation.h> // ClassA @interface ClassA : NSObject { } @end @implementation ClassA -(void) iMethod { NSLog(@"スーパークラスのインスタンスメソッドです。\n"); return; } @end // ClassB1 @interface ClassB1 : ClassA @end @implementation ClassB1 -(void) iMethod { NSLog(@"サブクラスのインスタンスメソッドです。\n"); return; } @end // ClassB2 @interface ClassB2 : ClassA @end @implementation ClassB2 @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... ClassB1 *instance_B1 = [[ClassB1 alloc]init]; ClassB2 *instance_B2 = [[ClassB2 alloc]init]; [instance_B1 iMethod]; [instance_B2 iMethod]; // 親には子のクラスが入れられる ClassA *bangai = instance_B1; [bangai iMethod]; } return 0; } ------------------------------------------------------------------------------ ★実行結果 サブクラスのインスタンスメソッドです。 スーパークラスのインスタンスメソッドです。 サブクラスのインスタンスメソッドです。

  • (クラス名.this.メソッド)って・・・?

    次のようなクラスで public class ClassA {   public static void main(String[]args)   {     new ClassA(); /* 構築A */   }   public ClassA()   {     new ClassI();   }   public class ClassI()   {     ClassA.this.MethodA(); /* 命令A */   }   public void MethodA()   {     System.out.println("HELLO");   } } この命令Aの部分の (クラス名.this.メソッド)というアクセス方法がよくわかりません とりあえす(ClassA.this)が構築Aの部分で生成された インスタンスではないかとおもうのですがそれで正しいのでしょうか? また インナークラスはインナークラスの定義されているクラス以外から インスタンスを生成できないのでしょうか? つまり次のクラスを追加して public class ClassB {   public ClassB()   {     new ClassA.ClassI(); /* 構築B */   } } ここの構築Bのように(この場合はダメの様ですが)他のクラスから 構築することです もし仮にできるとしたら そのときの命令Aの(ClassA.this)は一体なんの インスタンスを指すのでしょうか 急ぎのプログラムを作っているので たいへん不躾ですが、なるべく早くお答えをお願いします

    • ベストアンサー
    • Java
  • 配列であるメンバのコンストラクタを呼ぶ方法

    C++のクラスについて教えていただけないでしょうか。以下のような場合、 class ClassA {   int A; public:   ClassA(int a): A(a) {} }; class ClassB {   ClassA A; public:   ClassB(): A(10) {} }; class ClassC {   ClassA A[2]; public:   ClassC() {} //配列であるメンバのコンストラクタを呼び出したい }; ClassBがClassAのコンストラクタを呼ぶには上記のような方法で良いと思うのですが、ClassCのようにメンバが配列の場合、そのメンバのコンストラクタを呼ぶにはどのようにしたら良いのでしょうか。ご教授をお願いします。

  • 参照メンバを持つクラス

    ClassAとClassBにCMyDataオブジェクトを渡したいのですが、メモリ上に同じデータのコピーを作りたくないので、コンストラクタがCMyDataの参照を受け取る設計にしました。こうすることで、CMyDataの実体はメモリ上に1つしか存在しないことになります。 ただ、クラスが、自身が管理していない外部領域にあるデータへの参照を使って仕事をするというのに違和感を感じます。 完全コンストラクタというデザインパターンがあって、クラスのインスタンスを生成する時に必要な全てのデータを渡すのが正しい流儀だそうです。 しかしこのClassA(B)の設計では、ClassA(B)の寿命が終わるまで参照先のデータが生きているとは限りません。もっといい設計はないでしょうか?ちなみにCMyDataは実際にはかなり大きなデータで、一時的であってもコピーを複数持ちたくないのです。ClassAとClassBは、実際は他のデータも参照するため1つのクラスにはしたくないのです。 class CMyData { // 色々なデータ }; class CMain { CMyData* myData; // ファイルからデータを読み込んで生成 ClassA* objA; ClassB* objB; void ReadFile() { myData = new CMyData(); // ファイルからデータを読み込みCMyData構築 } void Init() { ReadFile(); objA = new ClassA(*myData); // 自身のメンバ変数の参照でClassAを構築 objB = new ClassB(*myData); } void DoProcess() { Init(); // 実行は一度だけ objA->hoge(); // ClassAに仕事をさせる objB->foo(); // ClassBに仕事をさせる } } class ClassA { CMyData& m_data; public: ClassA(CMyData& data) m_data=data; // CMyDataオブジェクトを参照で受け取る void hoge(); } class ClassB { CMyData& m_data; public: ClassB(CMyData& data) m_data=data; // CMyDataオブジェクトを参照で受け取る void foo(); }

  • 継承元クラスのプロパティを参照する手段

    お世話になります。 ActionScrip3に関する質問です。 現在、カスタムクラスを勉強しております。 外部クラスでClassA、ClassBを作成し、 ClassAにある処理の途中でClassBを実行し、ClassBの中からClassAのプロパティを参照しにいく 処理を行いたいと思い、ClassBのコンストラクタからClassAのプロパティをtraceしました。 プロパティppt2は「かきくけこ」が出力されましたが、ppt1は「null」になってしまいました。 恐らく、タイムラインからClassAに対して設定したプロパティの値は見にいけていないようですが、 タイムラインから設定したプロパティの値を継承したClassBから参照しにいく方法はありますでしょうか? 下記ソースと同じ方法でなくても結構ですので、タイムラインから設定した スーパークラスのプロパティ値をサブクラスから参照・変更できる方法を ご教授いただければと存じます。 お手数ではありますが、宜しくご教授ください。 宜しくお願いいたします。 /* タイムライン側の処理 -----------------------*/ var test:ClassA = new ClassA(); test.ppt1 = "あいうえお"; test.goNext(); /* ClassAの処理 -----------------------*/ package {  // インポート記述は省略  public class ClassA {   var ppt1:String;   var ppt2:String = "かきくけこ";   // コンストラクタ   public function ClassA() { }   public function goNext():void {    var classb:ClassB = new classB();   }  } } /* ClassBの処理 -----------------------*/ package {  // インポート記述は省略  public class ClassB extends ClassA {   // コンストラクタ   private function ClassB() {    trace(ppt1);    trace(ppt2); }  } }

    • ベストアンサー
    • Flash
  • C++ クラス概念

    以下の違いがよく理解できていません。 どなたかご教授お願い致します。 (1)クラスのメンバー変数に static を付けた場合と、 メンバーではない変数に static を付けた場合の違い (2)クラスのメンバー関数に static を付けた場合と、 メンバーではない関数に static を付けた場合の違い [プログラム例] class MyClass { public: static int internalCount; static void func(MyClass& a) {/* ... */} }; static int i; static void f(MyClass& a) { /* ... */ }

  • JAVA初心者です。

    javaにおけるprivateメンバの動きについて伺いたいことがございます。 基本的にスーパークラスのprivateなメンバへはメソッド・フィールドともにサブクラスからは アクセスできないとのことですが、 例えば、以下のようなコードがあるとします。 //スーパークラスの定義 class SuperClass{ private String privateString = "スーパークラスのプライベートメンバ"; public void getter(){ System.out.println(this.privateString); } } //サブクラス class SubClass extends SuperClass{ } //実行クラス class RunClass { static public void main (String args []){ SubClass subObj; subObj = new SubClass(); subObj.getter(); } } 上記のようなコードの場合サブクラスのインスタンスであるsubObjが スーパークラスのpublicなメソッドを通じてサブクラスからスーパークラスのprivateメンバへアクセスが できてしまっています。 これは、スーパークラスのprivateが隠蔽されていないのではないでしょうか? 果たして、このときいったサブクラスのインスタンスのsubObjはどういった動きをしているのでしょうか?

    • ベストアンサー
    • Java
  • 「static宣言されているメンバ関数」は、「インスタンスメソッド」な

    「static宣言されているメンバ関数」は、「インスタンスメソッド」なのでしょうか? それとも、「クラスメソッド」なのでしょうか? 先日、下記内容で質問して、その時は分かったつもりだったのですが、 やっぱり分かってなかったようなので、教えてください。 ▽「クラス関数」「メンバ関数」「メソッド」の違いを教えてください。   http://okwave.jp/qa/q5858806.html 例) ▽前提 ・Aクラスのインスタンスa ・static宣言されたpublicメソッド「static_public_method」 ・static宣言されていないpublicメソッド「public_method」 ▽メンバ関数呼び出し ・$a->static_public_method() ・A::static_public_method() ・A::public_method() このとき、「$a->static_public_method()」は、インスタンス経由でアクセスすることになるので、 「インスタンスメソッド」になるのでしょうか。それとも、static(静的)宣言しているので、「クラスメソッド」になるのでしょうか? また、「A::static_public_method()」や、「A::public_method()」は、どちらになるのでしょうか? ※現在、頭の中がこんがらがっているのは、下記3点です。どれかひとつでも構わないので、分かりやすい考え方等あれば、ぜひ教えてください。 ・「static宣言したメンバ関数」は、「インスタンスメソッド」? 「クラスメソッド」? ・「スタティック」宣言してるのに、メンバ関数へ、「->(アロー演算子)」(オブジェクト経由)でアクセスできる理由 ・「A::static_public_method()」と「A::public_method()」の違い

    • ベストアンサー
    • PHP
  • 別クラスのmainメソッドの実行

    とあるクラス「ClassA」の業務メソッドから、 別のクラス「ClassB」の「public void main」メソッドを呼び出す ことは、可能なのでしょうか?。 補足しますと、JMS経由でメッセージを受け取り、それを トリガにして別Javaアプリを起動したいのです。 浅いご説明で恐縮ですが、アドバイス頂けましたら幸いです。

専門家に質問してみよう