クラス(not インスタンス)を関数に渡すには?

[戻る]
おみおみ 2006/01/27(金) 22:43:34
識者の方教えてください。

.net2003 MFCです。

ある関数内で、CDialogクラスの派生クラスを生成したいのですが、
呼ぶたびにクラスは異なります。
今は関数を呼ぶ前にnewしてるのですが、
以下のようなことができればベターです。
しかし、やはり無理なのでしょうか?

他にいい代替案があればお願いします。

void Kansu( クラスのインスタンスではなく、クラス名をパラメータとして渡したい )
{
  派生クラス pDlg = new 派生クラス;
  pDlg->Create( this );
}

おみおみ 2006/01/27(金) 22:51:36
リソースIDがいりますね。

void Kansu( クラス名, INT iIDD )
{
  派生クラス pDlg = new 派生クラス;
  pDlg->Create( iIDD, this );
}

今は、

void Kansu( CDialog* pDlg, INT iIDD )
{
  pDlg->Create( iIDD, this );
}

として、

CDlg××* pDlg = new CDlg××;
Kansu( pDlg, IDD××);

としてます。

RAPT 2006/01/27(金) 23:49:22
そのクラス名は、コンパイル時点で定められますか?

コンパイル時点で確定できるなら、template が使えませんか?
実行時だと無理です。


#include <iostream>
#include <string>

template<class T>
class Base
{
public:
    void kansu()
    {
        T* pT = static_cast<T*>(this);
        pT->CallMethod();
    }
};


class DeriveA : public Base<DeriveA>
{
public:
    void CallMethod()
    {
        std::cout << "A::CallMethod() called.\n";
    }
};

class DeriveB : public Base<DeriveB>
{
public:
    void CallMethod()
    {
        std::cout << "B::CallMethod() called.\n";
    }
};

class Driver
{
public:
    template<class T>
    void test(Base<T>* pT)
    {
        pT->kansu();
    }
};

int main(void)
{
    DeriveA a;
    DeriveB b;
    Driver d;

    d.test(&a);
    d.test(&b);

    return 0;
}

RAPT 2006/01/28(土) 00:04:15
# どこかで見たと思ったら

クラス名から動的にオブジェクトを作成
http://forums.belution.com/ja/cpp/000/048/96s.shtml

おみおみ 2006/01/28(土) 10:35:14
ありがとうございます。
ちょっと理解に時間がかかりそうですが、
勉強してみます。

reshia [HomePage] 2006/01/30(月) 11:13:59
こんな↓でよければ、どうぞ。

//---------------------------------
#include <iostream>
#include <string>

class Super {
public:
  Super() {}
  ~Super() {}
public:
  virtual const char* run()=0;
};

class SubA : public Super {
public:
  SubA() : Super() {}
  ~SubA() {}
  static const char* GetName() {
    return "SubA";
  }
  virtual const char* run() {
    return "SubA";
  }
};

class SubB : public Super {
public:
  SubB() : Super() {}
  ~SubB() {}
  static const char* GetName() {
    return "SubB";
  }
  virtual const char* run() {
    return "SubB";
  }
};

Super* GetInstance(std::string name) {
  if (name == SubA::GetName() ) {
    return new SubA();
  } else if (name == SubB::GetName() ) {
    return new SubB();
  }
  return 0;
}

int main(int argc, char* argv[])
{
  using namespace std;

  Super* instance;
  instance = GetInstance( string("SubA") );

  cout << "instance name is \"";
  cout << ((instance != 0) ? instance->run() : "null") << "\"" << endl;

  delete instance;
  return 0;
}
//---------------------------------

ってこともできますけど。
もう少し、スマートにすると、

//---------------------------------
#include <iostream>
#include <string>

class Super {
public:
  Super() {}
  ~Super() {}
public:
  virtual const char* run() =0;
};

class SubA : public Super {
public:
  SubA() : Super() {}
  ~SubA() {}
  static const char* GetName() {
    return "SubA";
  }
  virtual const char* run() {
    return "SubA";
  }
};

class SubB : public Super {
public:
  SubB() : Super() {}
  ~SubB() {}
  static const char* GetName() {
    return "SubB";
  }
  virtual const char* run() {
    return "SubB";
  }
};

class InstanceManager {
private:
  Super* instance;
public:
  InstanceManager() : instance(0) {}
  ~InstanceManager() {
    if (instance != 0) {
      delete instance;
    }
  }
  Super* const GetInstance(std::string name) {
    if (instance != 0) {
      delete instance;
      instance = 0;
    }

    if (name == SubA::GetName() ) {
      instance = new SubA();
    } else if (name == SubB::GetName() ) {
      instance = new SubB();
    }

    return instance;
  }
  Super* const GetInstance() {
    return instance;
  }
};

int main(int argc, char* argv[])
{
  using namespace std;

  InstanceManager im;

  Super* instance = im.GetInstance("SubA");

  cout << "instance name is \"" << ((instance != 0) ? instance->run
() : "null") << "\"" << endl;
  return 0;
}
//---------------------------------


かと。。
こんなでどうでしょうか。

ま、子クラスが増えると、GetInstanceのif-elseを
書き直す必要があるので、汚いですけど。。
#ま、子クラスが乱立している状況も汚いですけど。

Ban 2006/01/30(月) 12:27:23
>  static const char* GetName() {

単一コンパイラでかまわないなら、typeid という手も。

で、サブクラスの実装は template 化してみる。

古いスレッドには追加発言できません。