如何将typename传递给我不想模板化的类?

时间:2012-12-03 20:20:00

标签: c++ templates inheritance

我有以下问题(简化版):

Interface X;
class Y : public X { ... }
class Z : public X { ... }

class A
{
    map<int, X> m;
    init() { X bla = new Y or Z; map.insert(...) }
}

我想在A的创建时指定Y或Z,从而根据指定的类型获得不同的功能。目前我可以“模板化”A,但这意味着我为A定义的每个函数都必须指定模板,即使我只需要在一个方法中使用它。另外,我使用的是g ++ 4.2.4,这意味着我无法将我的函数实现与头文件分开。

3 个答案:

答案 0 :(得分:3)

听起来像模板确实有点过分,而某种形式的依赖注入更合适。您可以将X的特定实例传递给A::init,例如:

init(X &bla) { map.insert(...); }

或传递工厂功能:

init(X (*factory)()) { X bla = factory(); map.insert(...); }

或者执行其中任何一项,但将实例或工厂函数传递给A的构造函数。

答案 1 :(得分:2)

如果使用new似乎实际上是map<int, X*> mX* bla=...,那么您可以“模板化”init(),创建Y }或Z取决于其模板参数。

或者,您可以拥有X的工厂方法 - 派生对象,根据Y *返回Z *enum;或让调用者init指定一个返回相应X派生类型的工厂函数。

答案 2 :(得分:2)

  

...即使我只需要在一种方法中使用它......

在这种情况下通常做的是将未模板化的公共功能移动到基类,并定义继承基本功能的模板化A。即:

class A_base {
    // common things go here, they can be implemented in a .cpp file.
};

// This is the part that depends on T
template<class T>
class A : public A_base
{
    map<int, T> m;
    void init() { T *bla = new T; map.insert(...) }
};

这是减少代码膨胀的常用技术。如果A_base需要调用A的方法,则可以将其设为virtual