2011-10-16 4 views
10

У меня есть шаблон класса, и мне нужно, чтобы объявить объект этого класса, без определения параметров типа, так что я могу определить их условно позже, например:Динамический шаблон Инстанцирование

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 за явно задаваемый вопрос с минимальным, полный пример – Flexo

+1

Согласованный. Вероятно, он имеет 100000dupes, но это довольно ясно и хорошо спрошено. – Puppy

ответ

7

Ну , вы, конечно, не можете этого сделать. Вы должны сделать проистекают из другого класса, например:

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 выглядит многообещающим, но что именно происходит с указателем, когда вы назначаете его подклассу этого типа? Это (для лучшего термина) относится к этому типу или к чему-то ...? (как это делает память, которую он указывает, чтобы настроить, чтобы соответствовать памяти, необходимой для объекта субкадров?). Каковы правила для отношения базового класса/подкласса – user965369

+1

Точно. Причина, по которой вы не можете сделать это, как в OP, заключается в том, что шаблоны полностью расширяются во время компиляции; во время выполнения экземпляры шаблона являются просто регулярными классами и функциями. Их шаблонные отношения теряются после расширения шаблона. – tdammers

+0

@ user965369: Это основной полиморфизм; каждый экземпляр шаблонного класса A является подклассом класса B, и соответственно неявное выполнение кастингов. – tdammers

3

Самый простой способ сделать это, чтобы использовать другую функцию.

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)); 
} 

Это сохраняет всю информацию о типе и не зависит от наследования. Недостатком наследования является то, что T не может появляться в каких-либо функциональных интерфейсах, но в такой ситуации он может.

2

Шаблоны расширены во время компиляции, так что ваша проблема на самом деле так же, как следующее:

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); 
} 

Надеюсь, если вы видели код выше, можно подумать, что (как и «может быть, я следует использовать шаблоны »)« Мне понадобится общий базовый класс для этого, иначе я буду refactor ».

Когда вы создаете два типа во время компиляции с использованием шаблона класса, этот вывод является тем же.

  • Я бы рекомендовал рефакторинг для решения таких задач, как DeadMG; создавая иерархию наследования, чтобы обойти недостаток логики программы, программирование в обратном направлении!
-1

Вы можете использовать пустой указатель в то время как создать объект класса А
Посмотрите на следующий код:

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;  
    } 
} 
Смежные вопросы