2011-10-16 10 views
10

Tengo una plantilla de clase, y tengo que declarar un objeto de esa clase, sin definir los parámetros de tipo, de modo que pueda definirlos condicional después, por ejemplo:plantilla dinámica de instancias

template<typename T> 
class A{ 
public: 
    A(T v){var = v}; 
    ~A(){}; 

    T var; 
} 

int main(){ 
    A<>* object; // Or sometihng along these lines...? 
    if(/* something*/) 
     object = new A<float>(0.2f); 
    else{ 
     object = new A<int>(3); 
    } 
} 
+0

+1 para una pregunta claramente pedido con un mínimo, ejemplo completo – Flexo

+1

acuerdo. Probablemente tenga 100000 dudes, pero es bastante claro y está bien hecho. – Puppy

Respuesta

7

Bueno , ciertamente no puedes hacer eso. Vas a tener que hacer una derivación de otra clase, por ejemplo:

template<typename T> 
class A : public B { 
public: 
    A(T v){var = v}; 
    ~A(){}; 

    T var; 
} 

int main(){ 
    B* object; 
    if(/* something*/) 
     object = new A<float>(0.2f); 
    else{ 
     object = new A<int>(3); 
    } 
} 
+0

Ahh que parece prometedor, pero ¿qué pasa exactamente con el puntero cuando lo asigna a una subclase de ese tipo? ¿(Para un mejor término) se lanza a ese tipo o algo ...? (¿Cómo lo hace la memoria asignada apunta para ajustarse a la memoria que necesita el objeto del subcals?). Cuáles son las reglas para una relación de clase base/subclase – user965369

+1

Exactamente. La razón por la que no se puede hacer como en el OP es que las plantillas están completamente expandidas en tiempo de compilación; en el tiempo de ejecución, las instancias de plantilla son solo clases y funciones regulares. Su relación basada en plantilla se pierde después de la expansión de la plantilla. – tdammers

+0

@ user965369: Es un polimorfismo básico; cada instanciación de la clase A con plantilla es una subclase de clase B, y la conversión implícita funciona en consecuencia. – tdammers

3

La forma más sencilla de hacerlo es utilizar otra función.

template<typename T> void other_stuff(A<T>* object) { 
    // use T here 
} 
int main() { 
    if (condition) 
     other_stuff(new A<float>(0.2f)); 
    else 
     other_stuff(new A<int>(3)); 
} 

Esto mantiene toda la información del tipo y no depende de la herencia. La desventaja de la herencia es que T no puede aparecer en ninguna interfaz de función, pero con esta situación sí puede.

2

plantillas se expanden en tiempo de compilación, por lo que su problema es realmente lo mismo que la siguiente:

struct A_float {   // struct is easier when everything's public 
    A(float v) : var(v) {} // (use the ctor-initializer please!) 
    ~A() {} 

    float var; 
};       // don't forget the semicolon 

struct A_int { 
    A(int v) : var(v) {} 
    ~A() {} 

    int var; 
}; 

int main() { 
    WhatType* object; // What type here? 
    if (/* something*/) 
     object = new A_float(0.2f); 
    else 
     object = new A_int(3); 
} 

Con suerte si viste el código anterior, se podría pensar (así como "tal vez debería usar plantillas ")" Voy a necesitar una clase base común para esto, o bien voy a refactor ".

Cuando genera los dos tipos en tiempo de compilación utilizando una plantilla de clase, esta conclusión es la misma.

  • Recomendaría la refactorización, buscando una solución como DeadMG's; ¡crear una jerarquía de herencia solo para solucionar un problema de flujo lógico del programa es programar hacia atrás!
-1

Puede utilizar puntero nulo, mientras que crear el objeto de la clase A
Mira siguiente ejemplo de código:

template<typename T> 
class A 
{ 
public: 
    A(T v){var = v;}; 
    A(){}; 
    ~A(){}; 
    T var; 
}; 
int main(){ 
    A<void *> object; 
    if(1){ // do this 
     object = new A<float>(0.31f); 
     // type cast void pointer to get value 
     cout<<*(float*)object.var;  
    } 
    else{ // else do this 
     object = new A<int>(34); 
     // type cast void pointer to get value 
     cout<<*(int*)object.var;  
    } 
} 
Cuestiones relacionadas