Method 1: If your class names have a uniform prefix, such as C, C1, C2, C3, you can use macros to create them
class C
{
public :
virtual void run() = 0;
};
class C1 : public C
{
public :
void run() { printf("C1 run\r\n"); }
};
class C2 : public C
{
public :
void run() { printf("C2 run\r\n"); }
};
#define NEW_C_INSTANCE(class_id) new C##class_id();
int main()
{
//int id = 2; //不可以这样
//C* c = NEW_C_INSTANCE(id);
//C* c = NEW_C_INSTANCE(1);
C* c = NEW_C_INSTANCE(2);
c->run();
getchar();
return 0;
}
Advantages: The type is determined during the compile time, and the code is efficient.
Disadvantages: Need to have a unified naming prefix.
The parameters of NEW_C_INSTANCE cannot be assigned externally, only fixed codes can be written.
Relevant header files need to be defined in advance, which is less flexible.
Method 2: Use static function pointer to create
class S;
typedef S* (*s_creator_function)();
class S
{
public:
static S* create(){ return NULL;}
virtual void run() = 0;
};
class S1 : public S
{
public:
static S* create(){ return new S1();}
void run() {printf("S1 run!\r\n");}
};
class S2 : public S
{
public:
static S* create(){ return new S2();}
void run() {printf("S2 run!\r\n");}
};
class S_Factory
{
public:
void registerCreator(int id, s_creator_function func )
{
map.insert( std::pair<int,s_creator_function>(id, func) );
}
S* create(int id)
{
std::map<int, s_creator_function>::iterator it;
it = map.find(id);//在map中查找创建函数
if( it != map.end() )
return (it->second)();
return NULL;
}
private:
std::map<int, s_creator_function> map;
};
S_Factory sFactory;
int main()
{
sFactory.registerCreator(1, S1::create);
sFactory.registerCreator(2, S2::create);
//int n = 1;
int n = 2;
S* s = sFactory.create(n);
s->run();
getchar();
return 0;
}
Advantages: flexible expansion.
Disadvantages: Slightly complicated when creating. The rules and management are not good, and it is hard to check when something goes wrong.