Método 1: si los nombres de sus clases tienen un prefijo uniforme, como C, C1, C2, C3, puede usar macros para crearlos
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;
}
Ventajas: los tipos se determinan durante la compilación y el código es eficiente.
Desventajas: Necesita tener un prefijo de nomenclatura unificado.
Los parámetros de NEW_C_INSTANCE no se pueden asignar externamente, solo se pueden escribir códigos fijos.
Los archivos de encabezado relevantes deben definirse de antemano, lo que es menos flexible.
Método 2: utilice el puntero de función estática para crear
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;
}
Ventajas: expansión flexible.
Desventajas: Ligeramente complicado a la hora de crear. Las reglas y la gestión no son buenas y no es fácil comprobar cuando algo sale mal.