gpt4 book ai didi

c++ - 在 C++ 中使用抽象基类和模板进行重构

转载 作者:行者123 更新时间:2023-11-30 05:23:11 25 4
gpt4 key购买 nike

我在尝试重构时遇到问题。我们有很多代码重复,我正在努力解决这个问题。我有以下类结构

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 friend 类以及如何以通用方式实现它。以前,此类仅适用于类型 ModelM0没有继承自 ModelBase .现在其他型号也继承自ModelBaseEM也需要与这些一起工作 - 这就是问题所在。我在 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;
}

我的问题:

  1. 如何更改上面的代码,以便在 EM<TModel>::getModel(int ag) 中我可以创建正确的 TModel使用 make在上面 - 我需要一个工厂吗?这将如何实现?

  2. ModelBase.h EM类被指定为友元类。这个我如何使通用的与 TModel 一起工作? ( ModelBase ) 正在使用的类型?

重要的是要注意这里这是一个重构问题,而不是我在方法中显示的代码是否正确或正确(为了简洁地突出我的问题已经被删减).重构是我唯一想要帮助的事情。非常感谢您的宝贵时间。

最佳答案

当我试图编译你的代码时,我不得不修复一些缺失的分号和缺失的类型( Tagtaurus::MsgTinyMatrix ),还修复了 getModel(int ag) 的声明和定义 |

通常,您需要向编译器表明 Bucket实际上是一个类型名称,而不是某种其他类型的参数。

对于声明,您有 2 个选择:

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;
}

忽略“这不对”。评论 - 我从您的示例代码中复制了它们。它实际上是完全正确的。

对于 friend声明,你需要添加一个模板版本,因为你想友好所有可能的模板实例化。我从 this answer 查到的(归功于 Anycorn)

template <class> friend class EM;

希望能解决您所有的问题。注意我使用了 template <class>因为你用过它。我个人更喜欢template <typename> .

关于c++ - 在 C++ 中使用抽象基类和模板进行重构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39306529/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com