I have a problem with some refactoring I am attempting. We have a lot of code duplication and I am trying to sort this out. I have the following class structure
IMessageSink.h:
class IMessageSink
{
public:
virtual ~IMessageSink() { };
virtual void process(const taurus::Msg& msg) = 0;
};
I have the following base class ModelBase.h which all models must inherit from, at this point please not the use of the 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;
};
The implementation of friend EM is not correct and I ask about this below. I then have a class that implements/inherits from 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);
};
with ModelM0.cpp implemented as:
ModelM0::ModelM0(Tag a) : ModelBase(a) { }
void ModelM0::calculate(double lambda)
{
// Do stuff.
}
The problem is with the EM friend class and how to implement this in a generic fashion. Previously, this class only worked with types ModelM0 which did not inherit from ModelBase. Now other models also inherit from ModelBase and EM needs to work with these as well - here lies the problem. I have the following definition in EM.h (which I have changed to a template so we can specify the type of ModelBase we are using TModel):
with EM.h as:
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);
}
The problem implementation is EM::Bucket& getModel(int ag);, in EM.cpp we have
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);
}
}
The above seems to be okay, my problem is the implementation of 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;
}
My questions:
How can I change the above code so that in
EM<TModel>::getModel(int ag)I can create the correctTModelusingmakein the above - do I need a factory and how would this be implemented?In
ModelBase.htheEMclass is specified as a friend class. How can this me made generic to work with theTModel(ModelBase) type being used?
It is important to note here that this is a refactoring question, not whether-or-not the code I have shown in the methods is proper or correct (this has been cut down in order to succinctly highlight my problems). The refactoring is the only thing I would like help with. Thanks very much for your time.