変数を式として指定することはできますか?

このQ&Aのポイント
  • 「new 式」で変数を式として指定することはできるかどうかについて疑問があります。具体的には、変数の内容に応じてclassAまたはclassBをnewするようなことをしたい場合に、簡潔な方法はないかと考えています。
  • クラスの多様なインスタンスを簡潔に生成する方法について検討しています。現在はクラスごとにnew演算子を使用してインスタンスを生成していますが、もっとシンプルな方法があるのではないかと考えています。
  • 変数を式として使用し、その内容によってclassAまたはclassBをnewする方法を知りたいです。forループを使用して複数のインスタンスを生成する際に、より効率的な方法を模索しています。
回答を見る
  • ベストアンサー

「new 式」 で、変数を 式 として指定することはできますか?

「new 式」 で、変数を 式 として指定することはできますか? 例えば次のような感じで、変数clの内容によりclassAあるいはclassBをnew するようなことがしたいです。 class base [ ... }; class classA : public base { .... }; class classB : public base { .... }; classA* ca; classB* cb; base* cl; cl = classA; ca = new cl; cl = classB; ca = new cl; これにより、多種のclassをnewする際にいちいち pa = new classA; pb = new classB; pc = new classC; pd = new classD; ............ としないで、 for (n=0; n<xxx; n++) p[n] = new cl[n]; …みたいに簡潔に書けないかなと考えてます。 よろしくお願いします。

  • zuntac
  • お礼率81% (307/377)

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

  • ベストアンサー
回答No.3

VS2008(VC++9)だとfunction,lambda,arrayが使えないので代わりにこんなかんじ: #include <iostream> #include <map> #include <string> using namespace std; class base { public: virtual void hello() const =0; }; class classA : public base { void hello() const { cout << "classA\n"; }}; class classB : public base { void hello() const { cout << "classB\n"; }}; class classC : public base { void hello() const { cout << "classC\n"; }}; class classD : public base { void hello() const { cout << "classD\n"; }}; base* makeA() { return new classA; } base* makeB() { return new classB; } base* makeC() { return new classC; } base* makeD() { return new classD; } int main(){ typedef base* (*createfn)(); map<string,createfn> factory; factory["classA"] = &makeA; factory["classB"] = &makeB; factory["classC"] = &makeC; factory["classD"] = &makeD; const char* names[] = { "classA", "classB", "classC", "classD" }; for ( int i = 0; i < 4; ++i ) { base* p = factory[names[i]](); // 名前からクラスを生成 p->hello(); delete p; } }

zuntac
質問者

お礼

回答、ありがとうございます。 最初のListは理解できなかったのですが、今回のは良く分かりました. newしたobjectのポインタを同じクラスのポインタに代入する方法を 含めて勉強してみます。

その他の回答 (3)

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

結局のところ「まとめてしまう」と (プログラムの字面上) base へのポインタにしかならないので, 派生クラスへのポインタにしようとしたらダウンキャストが必要になります. 仮想関数があるなら dynamic_cast が安全かな. ただ, まとめる一方で「派生クラスに独自のメソッドがある」状況が適切なのかどうかはちょっと不明です. しょうがないこともあるけど, 「不自然な処理をしている」という可能性もないわけではないです.

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

ん~, p[n] = new cl[n]; 書くとして, p の型はどうするつもりなんだろう. オブジェクト指向的には class base { virtual base *create() = 0; }; class classA : public base { classA *create() { new classA; } }; (以下略) として base *p = anObject->create(); というのがよくある?

zuntac
質問者

補足

回答ありがとうございます。 生成済みのInstanceから子を産ませるという方法でしょうか。 この質問ですこし考えたのですが、create()したものをbase のpointerに入れてもclassAなどの独自methodにはアクセス できないので、同じ派生クラスのポインタに代入できるような 方法を勉強してみたいと思います。

回答No.1

うーん...やれなくはないけどエレガントじゃありませんよ。 #include <iostream> #include <map> #include <functional> #include <string> #include <array> using namespace std; class base { public: virtual void hello() const =0; }; class classA : public base { void hello() const { cout << "classA\n"; }}; class classB : public base { void hello() const { cout << "classB\n"; }}; class classC : public base { void hello() const { cout << "classC\n"; }}; class classD : public base { void hello() const { cout << "classD\n"; }}; int main(){ map<string,function<base*()>> factory; factory["classA"] = [](){return new classA;}; factory["classB"] = [](){return new classB;}; factory["classC"] = [](){return new classC;}; factory["classD"] = [](){return new classD;}; array<string,4> names = { "classA", "classB", "classC", "classD" }; for ( int i = 0; i < 4; ++i ) { base* p = factory[names[i]](); // 名前からクラスを生成 p->hello(); delete p; } } # Visual Studio 2010 (VC++10) で動作確認済

zuntac
質問者

補足

回答、ありがとうございます。 VC++2008 Exp で compile すると次の Errorが出ます。     'function' : 定義されていない識別子です。 対応方法を教えていただけますでしょうか。 よろしくお願いします。

関連するQ&A

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

    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のようにメンバが配列の場合、そのメンバのコンストラクタを呼ぶにはどのようにしたら良いのでしょうか。ご教授をお願いします。

  • Rails AR 深い階層のテーブル参照

    Rails ActiveRecord において、 深い階層のテーブルを参照するのに有効な方法はないでしょうか? 例:下記の構造で classD から classAのnameを取得する。 classA  1→n  classB  1→n  classC  1→n  classD □classA   id   name □classB   id   name   class_a_id □classC   id   name   class_b_id □classD   id   name   class_c_id #前提条件 classC, classB, classAが必ずしも存在するとは限らない。 classDからclassAを参照する際に、#前提条件にあるように、 classB or classCが存在しない(nil)場合、 > class_d.class_c.class_b.class_a.name とするとエクセプションが発生しますが、 これを回避するために、 if class_d.class_c and class_d.class_c.class_b and class_d.class_c.class_b.class_a class_d.class_c.class_b.class_a.name end のようにしていますが、煩わしくてしかたがありません。 実際はエラーログ出力等行っているため、さらに複雑な処理になっています。 もっとスマートなコーディング方法やアドバイスがありましたら宜しくお願いします。 #補足 (1) has_many :through を使ってショートカットが作れることを知りましたが、 今回の例のように、複数階層となる場合の記述方法がわかりません。 ご存知の方回答お願いいたします。 (2) そもそも前提条件に問題があるのではないかとも思っています。 前提条件にあるような状態にならない様な仕組みにする、 もしくは、そのような状態にならないよう管理する、等すべきでしょうか? 以上宜しくお願いいたします。

    • ベストアンサー
    • Ruby
  • クラスでnew宣言

    いつも御世話になっています。 クラス作成時に、 オブジェクト型(クラス型)を変数として宣言している時がある気がするのですが、ClassB classB = new ClassB(); この場合の利点は何かあるのでしょうか? 普通に考えれば、この記述を宣言することで、この宣言がされているクラス自身が、ClassBの実体を持つことになり、このクラスだけで多数のクラスの実体を利用できるようになる。 と思ったのですが。 クラスとしては、 ClassA { private ClassB classB = new ClassB(); } という場合です。 ここで、private ClassB classB;でない理由: むやみに、上記の書き方をすると、外部から書き換えられてしまう恐れがあるから、、なるべくその可能性を回避するため 宜しくお願いします。

    • ベストアンサー
    • Java
  • 参照メンバを持つクラス

    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
  • (クラス名.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
  • インクルード元を知りたい

    PHP5.2.4を使用しています。 [a.php] <?php include("b.php"); include("c.php"); $c = new classC(); [b.php] <?php class classB { } [c.php] <?php class classC { public function __construct() { $c = new classB();//←b.phpファイルがどこでインクルードされたか知りたい } } という3つのファイルがあり、a.phpにアクセスするとします。 c.phpファイルのコンストラクタでb.phpファイルにあるclassBを生成していますが、 これはa.phpファイルにおいて先にinclude("b.php");があるので c.phpファイル内でもclassBを認識できると思います。 そこでc.phpファイル内でb.phpファイルがどこでインクルードされたか(この例ではa.phpファイル) 調べる方法なり関数というのはあるのでしょうか?

    • ベストアンサー
    • PHP
  • プログレスバーについて

    サーバー上からファイルをダウンロードするアプリを 作成しているものです。 ClassAとClassBが存在するとして、 ClassAでファイルをダウンロードする処理を記述し、 ClassBでプログレスバーを含むダイアログを作成しています。 ClassAのファイル読み込みのループ処理のカウンターを プログレスバーのメンバー変数m_plgと同調させたい。 例 ClassA  for(i=0;i<count;i++){  } ClassB  m_plg.SetRange(0,count); m_plg.SetPos(i); かなり簡略化してます。 上記内容は実現可能だと思うのですが、メンバー変数の宣言部がおかしいのか m_plgは宣言されていませんとエラーがでます。 メンバー変数の理解不足だと思うのですが、このような処理を行いたい場合は どちらのClassにも認識されるようなコントロールのメンバー変数はどのようにして 宣言すればよろしいのでしょうか? 開発環境はVC++6.0 MFC ダイアログです。

  • new演算子で困っています。

    基底クラスclass1と派生クラスclass2でnewを使って同じサイズの2次元配列pとqを作ったのですが、メモリ内の同じ場所を参照してるみたいで、class2の配列qで配列の中身を書き換えたら、class1の配列pの中身も書き換えられているんですが、対処法があれば教えてください。 class class1{ protected:      int** p; public:     class1(int n)     {   int i;        *p=new int[n];        for(i=0;i<n;i++){          p[i]=new int[2];        }      }    :    : }; class class2 : public class1{     int** q; public:     class2(int n)     {   int i;        *q=new int[n];        for(i=0;i<n;i++){         q[i]=new int[2];        } }    :    : };

  • Equalsはどこから呼出してるのでしょうか?

    wpfの次のpublic override int GetHashCode()とpublic override bool Equals(object obj)とpublic override string ToString()にブレークポイントを設定し「開始」をすると起動時にEqualsで中断、コンボボックスをクリックするとToStringやGetHashCodeで中断しますが、これらの呼び出し元はどこなのでしょうか? 何卒、ご教授よろしくお願いします。 mainwindow.xaml <Grid> <ComboBox x:Name="comboBox" HorizontalAlignment="Left" Margin="200,138,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{x:Static local:classA.comblist}"/> </Grid> mainwindow.xaml.cs public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } class classA { public static classB[] comblist { get { classB[] List = new classB[3]; classB a1 = new classB(); a1.listb = "AAA"; List[0] = a1; classB a2 = new classB(); a2.listb = "BBB"; List[1] = a2; classB a3 = new classB(); a3.listb = "CCC"; List[2] = a3; return List; } } } class classB { private string _listb; public string listb { get { return _listb; } set { _listb = value; } } public override int GetHashCode() { return 1; } public override bool Equals(object obj) { return false; } public override string ToString() { return listb; } } ※長々と書き込みすいません、コード自体に意味はございません