Тот факт, что метод принимает «ключ», который, по-видимому, является действительно типом (тип возвращаемого компонента), указывает мне, что тип на самом деле не известен до времени выполнения.Если это так, то механизм времени компиляции, такой как шаблоны, не подойдет.
Единственный вариант - вернуть указатель на базовый класс.И, как правило, когда используется этот шаблон, против базового класса вызываются только виртуальные методы - поэтому фактический тип производного класса не имеет значения (поэтому не требуется static_cast или dynamic_cast).
Edit:
Как отметил PhilCK в комментариях, тип фактически известен во время компиляции.Если это так, то поиск динамического типа в действительности никогда не требовался, и можно было бы использовать простые фабричные методы:
class GameObject {
A getComponentA();
B getComponentB();
C getComponentC();
// etc.
}
// which is more or less identical to:
class ComponentFactory {
public:
virtual Component* create() = 0;
};
class GameObject {
std::map<std::string,ComponentFactory> m;
public:
GameObject() {
// presumably a private map has to be populated with string -> factory methods here
}
template<class T>
T* getComponent(const std::string& s) {
// either the static_cast is needed here, or an alternate (messier)
// implementation of getComponent is needed.
// it's still possible for the wrong type to be passed (by mistake)
// and the compiler won't catch it (with static_cast). Since this could lead
// to heap corruption the only safe way with this type of
// implementation is dynamic_cast.
return static_cast<T>(m[s].create());
}
};
// this doesn't even compile:
// return types:
class GameObject {
template <class T>
T* getComponent(const std::string& s) {
if (s == "A") return new A();
else if (s == "B") return new B();
// etc..
else throw runtime_error("bad type");
}
}
Таким образом, на мой взгляд, есть 2 варианта.
1) использовать простые фабричные методы, в которых шаблоны вообще не нужны.2) использовать реализацию метода map -> factory вместе с dynamic_cast (которая, кажется, лишает цели использования создания динамических типов) и на самом деле излишне сложна, если динамические типы не нужны