使用不带if-else的变量选择类 [英] Choosing a class using a variable without if-else

查看:60
本文介绍了使用不带if-else的变量选择类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




作为模拟程序的一部分,我有几个不同的模型

类,ModelAA,ModelBB等,它们都是派生的来自班级

继承BasicModel。

Hi,

As part of a simulation program, I have several different model
classes, ModelAA, ModelBB, etc., which are all derived from the class
BasicModel by inheritance.


>从命令行参数,我需要选择正确的$ b类型$ b
>From a command-line parameter, I need to choose the correct type of



要使用的模型,例如,如果参数model_name是aa,那么

选择ModelAA。


目前我这样做如下:


BasicModel * model;


if(model_name ==" aa"){

model = new ModelAA(a,b,c);

}


else if(model_name ==" bb" ;){

model = new ModelBB(a,b,c);

}


等,通过所有(很多)模型。

每个模型构造函数都采用相同的参数,如果这是任何

帮助。


一旦这个完成后,只有BasicModel中的虚函数才是cal led。

(但是在不同的

种型号中实施这些可能会有很大不同。)


它是我明白必须有一个更好的方法来启动

模型,这在添加新模型时更容易更新,例如

涉及某种阵列或map,将model_name字符串映射到

类名,但我不能解决语法问题(我有点像新手一样)。


我已经仔细查看了常见问题解答,我看不到任何与b $ b相关的内容(但如果我错了请纠正我)。任何建议或

指针将不胜感激。


非常感谢和祝福,

David。

model to use, for example if the parameter model_name is "aa", then
choose ModelAA.

Currently I do this as follows:

BasicModel* model;

if (model_name == "aa") {
model = new ModelAA(a,b,c);
}

else if (model_name == "bb") {
model = new ModelBB(a,b,c);
}

etc., through all the (many) models.
Each model constructor takes the same parameters, if this is of any
help.

Once this is done, only virtual functions in BasicModel are called.
(But the implementation of these can be very different in the different
kinds of model.)

It is clear to me that there must be a better way of initiating the
models, which is easier to update when a new model is added, e.g.
involving some kind of array or map, mapping the model_name string to
the class name, but I can''t work out the syntax (I am somewhat of a
newbie).

I have looked hard at the FAQ, and I cannot see anything that is
relevant (but please correct me if I''m wrong). Any suggestions or
pointers would be greatly appreciated.

Thanks and best wishes,
David.

推荐答案



David Sanders写道:

David Sanders wrote:

很明显对我来说,必须有更好的方式来启动

模型,这在添加新模型时更容易更新,例如

涉及某种数组或地图,将model_name字符串映射到

类名,但我无法解决语法问题(我有点像新手)。
It is clear to me that there must be a better way of initiating the
models, which is easier to update when a new model is added, e.g.
involving some kind of array or map, mapping the model_name string to
the class name, but I can''t work out the syntax (I am somewhat of a
newbie).



#include< map>

#include< string>

#include< iostream>


struct BasicModel {

virtual~BasicModel(){}

//用于识别它的功能

虚拟const char * sig()const = 0;

};


struct ModelAA:BasicModel {

ModelAA(int a,int b,int c){}

const char * sig()const {return" model aa" ;;}

};


struct ModelBB:BasicModel {

ModelBB(int a,int b,int c){}

const char * sig()const {return" model bb";}

};


BasicModel * make_model_aa(int a,int b,int c)

{

返回新的ModelAA(a,b,c);

}


BasicModel * make_model_bb(int a, int b,int c)

{

返回新的ModelBB(a,b,c);

}

typedef std :: map<

std :: string,

BasicModel *(*)(int,in t,int)

#include <map>
#include <string>
#include <iostream>

struct BasicModel{
virtual ~BasicModel(){}
// function to identify which it is
virtual const char * sig() const = 0;
};

struct ModelAA : BasicModel{
ModelAA(int a, int b, int c){}
const char * sig() const {return "model aa";}
};

struct ModelBB : BasicModel{
ModelBB(int a, int b, int c){}
const char * sig() const {return "model bb";}
};

BasicModel* make_model_aa(int a, int b, int c)
{
return new ModelAA(a,b,c);
}

BasicModel* make_model_bb(int a, int b, int c)
{
return new ModelBB(a,b,c);
}

typedef std::map<
std::string,
BasicModel* (*)( int,int,int)


model_map_type;
model_map_type;



int main()

{

model_map_type model_maker;

model_maker [ " aa"] = make_model_aa;

model_maker [&bb"] = make_model_bb;


BasicModel * pmaa = model_maker [" aa"]( 1,2,3);

std :: cout<< pmaa-> sig()<<''\ n'';


BasicModel * pmbb = model_maker [" bb"](1,2,3);

std :: cout<< pmbb-> sig()<<''\ n'';

}

int main()
{
model_map_type model_maker;
model_maker["aa"]= make_model_aa;
model_maker["bb"]= make_model_bb;

BasicModel * pmaa = model_maker["aa"](1,2,3);
std::cout << pmaa->sig() <<''\n'';

BasicModel * pmbb = model_maker["bb"](1,2,3);
std::cout << pmbb->sig() <<''\n'';
}


David Sanders写道:
David Sanders wrote:

作为模拟程序的一部分,我有几个不同的模型

类,ModelAA,ModelBB等,它们都是派生的来自班级

继承BasicModel。


从命令行参数,我需要选择正确的类型

要使用的模型,例如,如果参数model_name是aa,那么

选择ModelAA。


目前我这样做如下:


BasicModel * model;


if(model_name ==" aa"){

model = new ModelAA(a ,b,c);

}


else if(model_name ==" bb"){

model = new ModelBB(a,b,c);

}


等,通过所有(很多)型号。

每个模型构造函数采用相同的参数,如果这是任何

帮助。
As part of a simulation program, I have several different model
classes, ModelAA, ModelBB, etc., which are all derived from the class
BasicModel by inheritance.

From a command-line parameter, I need to choose the correct type of
model to use, for example if the parameter model_name is "aa", then
choose ModelAA.

Currently I do this as follows:

BasicModel* model;

if (model_name == "aa") {
model = new ModelAA(a,b,c);
}

else if (model_name == "bb") {
model = new ModelBB(a,b,c);
}

etc., through all the (many) models.
Each model constructor takes the same parameters, if this is of any
help.



我建议实施注册模型,其中每个

BasicModel子类必须在中心映射中注册其名称及其静态创建

例程。按名称创建BasicModel子类

对象的例程会查询此中心映射,以便将

类名与适当的创建例程进行匹配

已注册。如果找到例程,则调用它来创建所请求类型的

对象。

要强制注册,每个BasicModel子类都将继承自

" ClassMap"模板的模板'的类型参数是

BasicModel子类本身。每个BasicModel子类还必须实现两个静态例程(或者它不会编译):一个GetName()

例程(返回用于创建对象的名称)那个类)和

a静态Create()例程,它分配一个匹配的对象

类。


这是一个基本的如果您愿意尝试其中任何一个,请执行上述想法:


#include< iostream>

#include< map>

#include< string>


使用std :: map;

使用std: :string;


class BasicModel;


typedef map< string,BasicModel *(*)()ClassNameMap;


struct ClassMapBase

{

static ClassNameMap sClassMap;

};


模板< class T>

struct ClassMap:public ClassMapBase

{

ClassMap(const string& name = std :: string(" ;& ))

{

if(name.length())

{

std :: cout << 注册: << T :: GetName()<< " \ n";


sInstance.sClassMap [T :: GetName()] = T :: Create;

}

}

静态ClassMap sInstance;

};


class BasicModel

{

public:

BasicModel(){}

static

BasicModel * CreateByName(const string&姓名)

{

ClassNameMap :: iterator iter;


iter = ClassMapBase :: sClassMap.find(name);


if(iter!= ClassMapBase :: sClassMap.end())

{

return(* iter).second( );

}

返回NULL;

}

};


// ModelAA继承自ClassMap,从而自行注册


class ModelAA:public BasicModel,ClassMap< ModelAA>

{

public:

ModelAA():BasicModel(){}

//必需GetName()例程


静态字符串GetName()

{

return" aa" ;;
}


//必需Create()例程


static BasicModel * Create()

{

返回新的ModelAA;

}

};


//一些class static variables


ClassNameMap ClassMapBase :: sClassMap;


//自注册静态变量


模板< class T>

ClassMap< TClassMap< T> :: sInstance(T :: GetName());


int main( )

{

BasicModel * a = BasicModel :: CreateByName(" aa");


// a是a ModelAA *

}


节目输出:


注册:aa


Greg

I would suggest implementing a "registration" model, in which each
BasicModel subclass has to register its name and its static creation
routine in a central map. The routine that creates BasicModel subclass
objects by name would consult this central map in order to match the
class name with the appropriate creation routine that had been
registered. If a routine is found, then it is invoked to create an
object of the requested type.

To enforce registration, each BasicModel subclass would inherit from a
"ClassMap" template with the template''s type parameter being the
BasicModel subclass itself. Each BasicModel subclass would also have to
implement two static routines (or it would not compile): a GetName()
routine (returning the name used to create an object of that class) and
a static Create() routine that allocates an object of the matching
class.

Here is a basic implementation of the preceding ideas in case you would
like to experiment with any of them:

#include <iostream>
#include <map>
#include <string>

using std::map;
using std::string;

class BasicModel;

typedef map<string, BasicModel* (*)()ClassNameMap;

struct ClassMapBase
{
static ClassNameMap sClassMap;
};

template <class T>
struct ClassMap : public ClassMapBase
{
ClassMap(const string& name = std::string(""))
{
if (name.length())
{
std::cout << "Registering: " << T::GetName() << "\n";

sInstance.sClassMap[ T::GetName()] = T::Create;
}
}
static ClassMap sInstance;
};

class BasicModel
{
public:
BasicModel() {}

static
BasicModel* CreateByName( const string& name)
{
ClassNameMap::iterator iter;

iter = ClassMapBase::sClassMap.find( name );

if (iter != ClassMapBase::sClassMap.end())
{
return (*iter).second();
}
return NULL;
}
};

// ModelAA inherits from ClassMap thereby registering itself

class ModelAA : public BasicModel, ClassMap<ModelAA>
{
public:
ModelAA() : BasicModel() {}

// required GetName() routine

static string GetName()
{
return "aa";
}

// required Create() routine

static BasicModel * Create()
{
return new ModelAA;
}
};

// some class static variables

ClassNameMap ClassMapBase::sClassMap;

// the self-registering static variable

template <class T>
ClassMap<TClassMap<T>::sInstance( T::GetName() );

int main()
{
BasicModel * a = BasicModel::CreateByName("aa");

// a is a ModelAA *
}

Program Output:

Registering: aa

Greg





12月23日上午9:51,Greg < gre ... @ pacbell.netwrote:


On Dec 23, 9:51 am, "Greg" <gre...@pacbell.netwrote:

David Sanders写道:
David Sanders wrote:

作为一个模拟程序,我有几个不同的模型

类,ModelAA,ModelBB等,这些都是通过继承从类

BasicModel派生出来的。
As part of a simulation program, I have several different model
classes, ModelAA, ModelBB, etc., which are all derived from the class
BasicModel by inheritance.


从命令行参数中,我需要选择要使用的正确类型的

模型,例如参数model_name是aa,然后

选择ModelAA。
From a command-line parameter, I need to choose the correct type of
model to use, for example if the parameter model_name is "aa", then
choose ModelAA.


目前我这样做如下:
Currently I do this as follows:


BasicModel * model ;
BasicModel* model;


if(model_name ==" aa"){

model = new ModelAA(a,b,c) ;

}
if (model_name == "aa") {
model = new ModelAA(a,b,c);
}


else if(model_name ==" bb"){

model = new ModelBB(a,b,c);

}
else if (model_name == "bb") {
model = new ModelBB(a,b,c);
}


等,通过所有(很多)模型。

每个模型构造函数都采用相同的参数,如果这是任何

help.I会建议实现注册。模型,其中每个
etc., through all the (many) models.
Each model constructor takes the same parameters, if this is of any
help.I would suggest implementing a "registration" model, in which each



BasicModel子类必须在中心地图中注册其名称及其静态创建

例程。按名称创建BasicModel子类

对象的例程会查询此中心映射,以便将

类名与适当的创建例程进行匹配

已注册。如果找到例程,则调用它来创建所请求类型的

对象。

要强制注册,每个BasicModel子类都将继承自

" ClassMap"模板的模板'的类型参数是

BasicModel子类本身。每个BasicModel子类还必须实现两个静态例程(或者它不会编译):一个GetName()

例程(返回用于创建对象的名称)那个类)和

a静态Create()例程,它分配一个匹配的对象

类。


这是一个基本的如果您愿意尝试其中任何一个,请执行上述想法:


#include< iostream>

#include< map>

#include< string>


使用std :: map;

使用std: :string;


class BasicModel;


typedef map< string,BasicModel *(*)()ClassNameMap;


struct ClassMapBase

{

static ClassNameMap sClassMap;

};


模板< class T>

struct ClassMap:public ClassMapBase

{

ClassMap(const string& name = std :: string(""))

{

if(name.length())

{

std :: cout<< 注册: << T :: GetName()<< " \ n";


sInstance.sClassMap [T :: GetName()] = T :: Create;

}

}

静态ClassMap sInstance;

};


class BasicModel

{

public:

BasicModel(){}

static

BasicModel * CreateByName(const string&姓名)

{

ClassNameMap :: iterator iter;


iter = ClassMapBase :: sClassMap.find(name);


if(iter!= ClassMapBase :: sClassMap.end())

{

return(* iter).second( );

}

返回NULL;

}

};


// ModelAA继承自ClassMap,从而注册自己


class ModelAA:public BasicModel,ClassMap< ModelAA>

{

public:

ModelAA():BasicModel(){}


//必需GetName()例程


静态字符串GetName()

{

返回" aa" ;;

}
< br $>
//必需Create()例程


static BasicModel * Create()

{

return新的ModelAA;

}

};


//一些类静态变量


ClassNameMap ClassMapBase :: sClassMap;


//自注册静态变量


模板< class T>

ClassMap< TClassMap< T> :: sInstance(T :: GetName());


int main()

{

BasicModel * a = BasicModel :: CreateByName(" aa");


// a是ModelAA *

}


节目输出:


注册:aa


格雷格 - 隐藏引用文字 - 显示引用文字 -

BasicModel subclass has to register its name and its static creation
routine in a central map. The routine that creates BasicModel subclass
objects by name would consult this central map in order to match the
class name with the appropriate creation routine that had been
registered. If a routine is found, then it is invoked to create an
object of the requested type.

To enforce registration, each BasicModel subclass would inherit from a
"ClassMap" template with the template''s type parameter being the
BasicModel subclass itself. Each BasicModel subclass would also have to
implement two static routines (or it would not compile): a GetName()
routine (returning the name used to create an object of that class) and
a static Create() routine that allocates an object of the matching
class.

Here is a basic implementation of the preceding ideas in case you would
like to experiment with any of them:

#include <iostream>
#include <map>
#include <string>

using std::map;
using std::string;

class BasicModel;

typedef map<string, BasicModel* (*)()ClassNameMap;

struct ClassMapBase
{
static ClassNameMap sClassMap;
};

template <class T>
struct ClassMap : public ClassMapBase
{
ClassMap(const string& name = std::string(""))
{
if (name.length())
{
std::cout << "Registering: " << T::GetName() << "\n";

sInstance.sClassMap[ T::GetName()] = T::Create;
}
}
static ClassMap sInstance;
};

class BasicModel
{
public:
BasicModel() {}

static
BasicModel* CreateByName( const string& name)
{
ClassNameMap::iterator iter;

iter = ClassMapBase::sClassMap.find( name );

if (iter != ClassMapBase::sClassMap.end())
{
return (*iter).second();
}
return NULL;
}
};

// ModelAA inherits from ClassMap thereby registering itself

class ModelAA : public BasicModel, ClassMap<ModelAA>
{
public:
ModelAA() : BasicModel() {}

// required GetName() routine

static string GetName()
{
return "aa";
}

// required Create() routine

static BasicModel * Create()
{
return new ModelAA;
}
};

// some class static variables

ClassNameMap ClassMapBase::sClassMap;

// the self-registering static variable

template <class T>
ClassMap<TClassMap<T>::sInstance( T::GetName() );

int main()
{
BasicModel * a = BasicModel::CreateByName("aa");

// a is a ModelAA *
}

Program Output:

Registering: aa

Greg- Hide quoted text -- Show quoted text -



很好的设计,我唯一的输入是,通常不是一个好主意

让基类知道派生类 - 在你的情况下这个

知识纯粹是由id和指向工厂方法的指针,而不是

直接知识关联。


要完成设计,我会将CreateByName()方法移动到

ModelFactory类。通过这种方式,我们保持了基类的理想,而不是知道派生类,更重要的是,我们有一个设计

符合单一责任原则。

Nice design, my only input would be that its not usually a good idea to
have base classes know about derived classes - in your case this
knowledge is purely by id and pointer to factory method, instead of a
direct knowledge association.

To finish the design, I would move the CreateByName() method to a
ModelFactory class. This way we keep the ideal of base classes not
knowing about derived classes and more importantly, we have a design
the is compliant with the Single Responsability Principle.


这篇关于使用不带if-else的变量选择类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆