我正在尝试进行一些重构。我们有很多代码重复,我试图解决这个问题。我有以下类结构
IMessageSink.h :
class IMessageSink
{
public:
virtual ~IMessageSink() { };
virtual void process(const taurus::Msg& msg) = 0;
};
我有以下所有模型必须继承的基类 ModelBase.h ,此时请不要使用friend class EM
:
class ModelBase : public virtual IMessageSink
{
public:
ModelBase(Tag a);
void process(const taurus::Msg& msg);
void reset();
private:
friend class EM; // I will ask about this below.
virtual void calculate(double lambda) = 0;
};
friend EM
的实施不正确,我在下面提出这个问题。然后我有一个实现/继承自ModelBase
, ModelM0.h 的类:
class ModelM0 : public virtual ModelBase
{
public:
ModelM0(Tag a);
static ModelM0* ModelM0::make(Tag a)
{
ModelM0* m = new ModelM0(a);
m->reset();
return m;
}
private:
void calculate(double lambda);
};
将 ModelM0.cpp 实现为:
ModelM0::ModelM0(Tag a) : ModelBase(a) { }
void ModelM0::calculate(double lambda)
{
// Do stuff.
}
问题在于EM
朋友类以及如何以通用方式实现它。以前,此类仅适用于未从ModelM0
继承的类型ModelBase
。现在其他模型也继承自ModelBase
和EM
也需要使用这些 - 这就是问题所在。我在 EM.h 中有以下定义(我已将其更改为模板,因此我们可以指定ModelBase
使用TModel
的类型:
EM.h :
template <class TModel>
class EM : public virtual IMessageSink
{
public:
static EM* make(Tag a)
{
return new EM(a);
}
EM(Tag a);
~EM();
void process(const taurus::Msg& msg);
void run();
private:
struct Bucket
{
TModel* _model;
std::vector<TinyMatrix<1, 1> > _obs
};
EM::Bucket& getModel(int ag);
}
问题的实施是EM::Bucket& getModel(int ag);
,我们在EM.cpp
template<class TModel>
EM<TModel>::EM(Tag a) { }
template<class TModel>
EM<TModel>::~EM()
{
run();
}
template<class TModel>
void EM<TModel>::process(const taurus::Msg& msg)
{
int ag = getMessageCount(msg.type()); // External call.
if (ag <= 3)
{
Bucket& b = getModel(ag);
TModel* m = b._model;
m->process(msg);
}
}
以上似乎没问题,我的问题是getModel
template<class TModel>
EM<TModel>::Bucket& EM<TModel>::getModel(int ag)
{
// This is not right.
TModel* m;
m = TModel::make(getTag(ag)); // This is not right - I need a factory.
// ... Do stuff.
Bucket& b = // Get a bucket.
b._model = m;
return b;
}
我的问题:
如何更改上述代码,以便在EM<TModel>::getModel(int ag)
中我可以使用上面的TModel
创建正确的make
- 我是否需要工厂?这将如何实施?
在ModelBase.h
中,EM
类被指定为朋友类。我如何使用TModel
(ModelBase
)类型来使用泛型?
重要的是要注意这是一个重构问题,而不是我在方法中显示的代码是否正确或正确(为了简明扼要地强调我的问题,这已被删除) )。重构是我唯一想要帮助的事情。非常感谢你的时间。
答案 0 :(得分:1)
当我尝试编译代码时,我必须修复一些缺少的分号和缺少的类型(Tag
,taurus::Msg
,TinyMatrix
)并修复声明和定义getModel(int ag)
通常,您需要向编译器指出Bucket
实际上是类型名称而不是其他类型的参数。
对于声明,您有两个选择:
Bucket& getModel(int ag); // (1)
typename EM<TModel>::Bucket& getModel(int ag); // (2)
(1)隐含使用当前模板特化的Bucket类型。 (2)是显式类型用法以及编译器的typename
关键字,如上所述。
对于定义,您肯定需要typename
关键字,因为您已经超出了类定义上下文。
template<class TModel>
typename EM<TModel>::Bucket& EM<TModel>::getModel(int ag)
{
// This is not right.
TModel* m;
m = TModel::make(getTag(ag)); // This is not right - I need a factory.
// ... Do stuff.
Bucket& b = // Get a bucket.
b._model = m;
return b;
}
忽略&#34;这不对。&#34;评论 - 我从示例代码中复制了它们。它实际上是完全正确的。
对于friend
声明,您需要添加模板版本,因为您希望与所有可能的模板实例建立友好关系。我从this answer(Credits to Anycorn)
template <class> friend class EM;
希望能解决您的所有问题。注意我使用template <class>
后使用它。我个人更喜欢template <typename>
。