我有以下问题(简化版):
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,这意味着我无法将我的函数实现与头文件分开。
答案 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*> m
和X* 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
。