識者の方教えてください。
.net2003 MFCです。
ある関数内で、CDialogクラスの派生クラスを生成したいのですが、
呼ぶたびにクラスは異なります。
今は関数を呼ぶ前にnewしてるのですが、
以下のようなことができればベターです。
しかし、やはり無理なのでしょうか?
他にいい代替案があればお願いします。
void Kansu( クラスのインスタンスではなく、クラス名をパラメータとして渡したい )
{
派生クラス pDlg = new 派生クラス;
pDlg->Create( this );
}
リソース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××);
としてます。
そのクラス名は、コンパイル時点で定められますか?
コンパイル時点で確定できるなら、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;
}
ありがとうございます。
ちょっと理解に時間がかかりそうですが、
勉強してみます。
こんな↓でよければ、どうぞ。
//---------------------------------
#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を
書き直す必要があるので、汚いですけど。。
#ま、子クラスが乱立している状況も汚いですけど。
> static const char* GetName() {
単一コンパイラでかまわないなら、typeid という手も。
で、サブクラスの実装は template 化してみる。