C++で派生クラスオブジェクトを一括して取り扱う方法

このQ&Aのポイント
  • C++で派生クラスオブジェクトを一括して取り扱う方法を探しています。
  • 現在の方法ではコーディング量が非常に増えて非効率的です。
  • 同じクラスなので、一括して検索できる方法を知りたいです。ポインタを取得してから操作する予定です。
回答を見る
  • ベストアンサー

複数の派生クラスオブジェクトを一括して取り扱う方法

いつもお世話になっています。 C++でプログラムをしています。 classAの派生クラスとして、 classA-1、classA-2を作りました。 classAのオブジェクトには、 親クラスにおいて、重複しないIDを 定義しています。 classA{...} classA-1():public A classA-2():public A classA-1 A1[1000]; classA-2 A2[2000]; ここで、クラスAオブジェクト (派生クラスを含む)のうち、 特定のIDのオブジェクト、 例えば、ID=100番のものを 取り出して、何某かの処理をしたいのですが、 現在は、 for(i=0;i<1000;i++){ if(A1[i] == 100){...} } for(i=0;i<2000;i++){ if(A2[i] == 100){...} } のようにしています。 しかし、派生クラスの種類が増えてくると、 この方法はコーディング量が非常に増えて 非効率的です。 プログラム上も美しくありません。 できれば、 同じクラスなのですから、 for(i=0;i<1000;i++){ if(A[i] == 100){...} } のような形で一括して検索するようにしたいのです。 つまり1つの配列変数で 両方を扱えるようにしたいのです。 ただし、当該IDを持つ、ポインタさえ取得できれば、 それぞれの派生クラスに型キャストしてから 操作するつもりです。 target = (classA-2)A[5]; target.Action(); どなたか、参考URL、キーワード、アドバイス等 頂ければ助かります。 よろしくお願いします。 よろしくお願いします。 としており、効率的ではなくなってしまいます。

  • zico2
  • お礼率79% (27/34)

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

  • ベストアンサー
noname#5537
noname#5537
回答No.1

基底クラスのポインタを使えば,一律に扱えます。 A *a[1000]; a[0] = new A1; a[1] = new A2;  : for (i=0 ; i<1000 ; i++) {  if (a[i]->GetID() == 100) { ... } } さらに,仮想関数を使うとキャストも不要になります。 class A { public:  virtual void Action() { std::cout << "A" << std::endl; } }; class A1 : public A { public:  virtual void Action() { std::cout << "A1" << std::endl; } }; class A2 : public A { public:  virtual void Action() { std::cout << "A2" << std::endl; } }; // A *target = a[0]; a[0]->Action(); # new したら delete もお忘れなく。

zico2
質問者

お礼

連絡が遅くなってすみません。 ご教示ありがとうございます。 おかげさまで、うまくいきました。 基底クラスで変数宣言しておけば使えるなんて クラスのすばらしさをまた実感しました。 どうもありがとうございました。

その他の回答 (1)

noname#5537
noname#5537
回答No.2

> A *target = a[0]; > a[0]->Action(); ↑意味不明ですね。 zico2 さんの例に合わせて, A *target = a[0]; target->Action(); と書くつもりが…,ついうっかり。 もちろん, a[0]->Action(); だけでも OK です。

関連するQ&A

  • 基本クラスのポインタで、派生クラスのメンバ関数を呼び出す方法?

    VC++でプログラミングをしています。 A(基本クラス) B(派生クラス) を作成しました。Bは、Aの特別な場合です。 このとき、基本クラスAのポインタから、派生クラスBにのみあるメンバ関数を呼ぶことはできないのでしょうか? 基本クラスAにも同じ名前の関数があれば、仮想関数をオーバーロードすれば呼び出せるようですが、この関数は、基本クラスには不要なので、できれば使わないメンバ関数を基本クラスに書きたくありません。 (純粋仮想関数という方法もあるようですが、) 操作としましては、 Aのポインタ配列 A* a[100]を作成し 特別な場合のみ派生クラスBのメンバ関数だけを実行させたいのです。 派生クラスにのみあるメンバ関数を、Readとします。 for(i=0;i<100;i++){ if(派生クラスBの場合){ a[i]->Read() } } 現状では、コンパイルエラーで、 関数Readは、aのメンバ関数ではありませんとなってしまいます。 以上よろしくお願いします。

  • 基本クラスのポインタから、特定の派生クラスのメンバ変数を変更する方法?

    VC++でプログラミングをしています。 A(基本クラス) A1, A2, A3, ...(派生クラス) を作成しました。A1,A2,A3, ...は、Aの派生クラスです。 このとき、基本クラスAのポインタから、特定の派生クラスにのみ存在するメンバ変数m_dataのみ変更したいのですが、存在するかどうかをどのように判定して、値を変更すれば良いでしょうか? できれば、下記のような構造でループできるとありがたいです。 A* a[100] (その後、a[100]に、派生クラスA1,A2,A3,..を割り当て、  それらが、混在しているとします。) for(i=0 ; i<100 ; i++){ if(a[i]->m_dataが存在する場合){ (2)   a[i]->Set_m_data("m_dataの新しい値") (1)  } } (1)は、a[i]->m_data = "m_dataの新しい値" でも良いです。 現状では、m_dataがメンバでない派生クラスがあるので、 (2)のif文の判定自体ができず困っています。 よろしく御願いします。

  • C#におけるObjectのキャストについて

    こんにちは。 C#におけるObjectのキャストについて、基本的なことにつまずいてしまいました。 以下のような継承関係にあるクラスで、InvalidCastExceptionが投げられてしまいます。 public class ClassA {} public class ClassA_Ex : ClassA {} ClassA_Ex ex = (ClassA_Ex)new ClassA(); キャストできない訳はないと思うのですが…。 何か大きな見落としがありそうですが、よろしくお願いいたします。

  • 派生クラスの自動生成

    はじめまして。 表題の件に関して質問させていただきます。 Aを親とした派生クラスをn個作るとします。 B1,B2,B3…Bn これらのインスタンスをクラスCのコンストラクタで生成したいとします。 その再Aのポインタを使いたいです。 このような時num_Aという定数をnum_of_A.hh中でnとdefineして #include "num_of_A.hh" class C::C(){ for(int i=0;i<num_A;i++){ A *a[i]=new A(); } } とする以外の方法がないでしょうか? Aを派生させたBを作ると、自動的にその数をカウントしてくれて、Bの数を書いたヘッダファイルなどを用意せずともC中でその数だけ生成してくれる機構を作ることは可能なのでしょうか? 説明がわかりにくくてすみません。 ご存じのかたご教授よろしくお願いいたします。

  • 条件によって別のクラスのインスタンスを作成する場合

    大きな条件分岐があって、その条件によって別のクラスを同じ名前でインスタンス化し、以降で使いたいのですが、うまくコンパイルが通りません。考えてみればifブロックの中だけで有効なインスタンスになってしまうので、当たり前かも知れません。どのようにすれば、使えるようになるのでしょうか。 以下にコードを載せます。正しい書き方を教えて下さい。 よろしくお願いします。 if(条件A){ classA object; // objectという名前でclassAをインスタンス化 }else{ classB object; // objectという名前でclassAとは別のclassBをインスタンス化 } object.methodA(); // objectのmethodA関数を使用したい

  • Cookieを使ってオブジェクトの引渡しはできるか?.

     phpを勉強中の一アルバイトプログラマです.いろいろ弄くってみてよくわからないところがあるのですが,ひとつ質問させていただきたいと思います.  あるページから,別のページへオブジェクトを引き渡したいと思いました.一度ブラウザを終了しても引き続いて扱えるようにしたいと思っていたので,cookieを使って次のようにすることにしました. a.php: $obj = new ClassA(); setCookie( "cookie", serialize($obj), mktime("2010/8/1 00:00:00") );  マニュアルによるとserializeしたオブジェクトはプロパティの値しか保存されない,ということですので,勝手に推測して, b.php: $obj = (ClassA)unserialize($cookie);  としたところ,b.phpでparse errorが起こります.どうやらphpではクラス間のキャストができなさそうだ,というのはわかりますが,そうすると,処理の流れの中で一貫してひとつのオブジェクトを扱いたい場合,どのようにすればよいのでしょうか?.  ・・・家に帰ってきてから気が付いたのですが,オブジェクトをserializeしたstringには,クラス名の情報が含まれているようです.ということは,ひょっとしてクラス定義さえきっちりしておけばunserializeしたオブジェクトもきちんとクラスのインスタンスとしてあつかえるのか?.

    • ベストアンサー
    • PHP
  • 共通したクラス名を持つ複数のタグのIDを取得したい

    共通したクラス名を持つ複数のタグのIDを取得したい <div class="classA" id="id1">aaa</div> <div class="classB" id="id2">bbb</div> <div class="classA" id="id3">ccc</div> となっているHTMLファイルからjqueryで要素を取得するプログラムを作成しています この時、class="classA"となっているID(id1とid3)とテキスト(aaaとccc)をjqueryで取得する方法を考えています jqueryで、 var elements = $(".classA"); でclass名がclassAの要素の数を取得したり、 var id = $(".classA").attr("id"); でidを指定すれば取得することもできました しかし、これはjqueryがあらかじ

  • 多態性を利用して派生クラスの関数を呼びたい

    環境はVS2013,言語はC++です. 基底クラス側で,基底クラスのポインタを引数に受ける仮想関数を宣言し, 派生クラスでその実装をします. 派生クラス側で引数に派生クラスのポインタを受けて,派生クラスのメンバにアクセスできるようにしたいのです. 作成したサンプルを下記に示します. Hello()は関係ありません. また,これはあくまで簡略化したサンプルなだけなので,thisポインタからメンバにアクセスすればよいというものではありません. #include <iostream> class Base { public: int i; Base() :i(0) {} virtual void print(Base *p) { std::cerr << "Base : " << i << std::endl; } virtual void hello() = 0; }; class Super : public Base { public: int x; Super() : x(1) {} void print(Super *p) { std::cerr << "Super : " << p->x << std::endl; } void hello() { std::cerr << "hello" << std::endl; } }; int main(void) { Base *p; p = new Super; p->print(p); } 上記を実行した結果,Base::print()が呼び出されました. print関数の引数に派生クラスSuperの実態を差すBase型ポインタを与えたときに,Super::print()を呼び出せるようにするには,何か方法はありますか. p->print(p)の呼び出し部分をp->((Super*)p)にキャストしても結果は同じくBase::print()が呼ばれました. Base::print()の実装を無くした場合は,未解決の外部参照のコンパイルエラーが発生し, Base::print()を純粋仮想関数にした場合は,Super側でSuper::pirnt(Base*p)を実装しなければならないのか,抽象クラスのインスタンス化ができないというコンパイルエラーが発生します. これは,派生クラスとはいえ,引数リストの型が違うのでオーバーライドされていないということですよね. 引数をBase *p,Super *pからそれぞれvoid *pへ変更し,Super::print()内で(Super *)へキャストしなおしたところ,きちんとオーバーライドされ,うまくはいきました. しかしながら,この方法だと派生クラス側で実装する際に毎回キャスト処理を書かなくてはなりません. 他に何かきれいな方法はないでしょうか.

  • C#でのあるオブジェクトの共通部分を利用したい

    すみません。C#での質問をどこにすればいいかわからなかったので、こちらに投稿します。 まず、あるクラスAとBがあり、こちらのクラスは同一のスーパークラスを継承しています。 ここでAとB、双方ともに同じプロパティ(とりあえず年度とします)をもっているのですが、スーパークラスにはそのプロパティをもっていません。 ある処理でもらえるクラスはスーパークラスだとして、そこで年度を変更する場合 if (superClass is classA) {   classA cA = (classA)superClass;   cA.年度 = "2007"; } else {   classB cB = (classB)superClass;   cB.年度 = "2007"; } という感じで、 クラスがAの場合ならクラスAにキャストして変更 クラスがBの場合ならクラスBにキャストして変更 としないといけないと思います。 しかし行う処理は同じため、ここで何とか工夫してどちらのクラスでも同じコードで変更を行う事ができないでしょうか。 本来であればスーパークラス側で「年度」を定義しておくべきだと思われますが、このクラスは提供されているもので、こちらで変更できないのです。 このままだと同一のコードを大量にかかなくてはならず、困っておりますが、提供先にスーパークラス側に用意するか、あるいはもう一つスーパークラスを継承した抽象クラスを作って、それを継承して作れないかと頼んだところ、いろいろな理由があり難しいとの回答でした。 そこで受け取ったほうで何とか大量のコードを書かずに、うまくやる方法はないでしょうか? それともやはり無理で、逐一コードをかいていくしかないでしょうか?

  • 親クラスのフリをした子クラスの使い方を教えて下さい

    以前、QNo.3479089でお世話になった者です。類似というか、続きの質問です。 ClassAを継承するClassBがあり、条件によって、ClassAまたはClassBをインスタンス化して使います。 (ClassBは、ClassAのメソッドの一部をオーバーライドして、ClassB固有のメソッドも追加しています) ClassA* pObj = NULL; if( ある条件 ) {   pObj = new ClassA(); } else( その他の条件 ) {   pObj = new ClassB(); } pObj->common_method(); これが常套手段と伺ったのですが、ClassBがインスタンス化された場合、ClassB固有のメソッドmethodBを呼び出そうとすると、「ClassAにはmethodBが存在しない」といったようなコンパイルエラーが出ます。 pObj->methodB(); // ここで、エラー それで、エラーを解消するために、「その他の条件」の時に、dynamic_castを使ってみました。 if( その他の条件 ) {   ClassB* pObj2 = dynamic_cast<ClassB*>( pObj );   pObj2->methodB(); } 上記でコンパイルエラーは解消したのですが、なにか、非常にめんどくさいです。 また、ClassAのフリをした実体ClassBを使っているのだから、オーバーライドしているメソッドもdynamic_castをしないと呼び出されないような気がします。 結局、親のフリした子クラスを作成する場合、こんなにめんどくさいことをしないといけないのでしょうか? それともこのやり方はおかしいですか? この場合、どういうふうにするものなのか、教えて下さい。よろしくお願いします。

専門家に質問してみよう