微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在重用基本模板实现时替代虚拟继承

如何解决在重用基本模板实现时替代虚拟继承

在我正在处理的一个项目中,我们使用一种模式,其中我们有定义接口的纯抽象类,以及可以使用不同模板参数实例化的模板实现,这些模板参数用于许多事情,包括依赖注入。类似的东西:

struct Base {
  virtual int getVal() = 0;
};

template <typename DI>
struct BaseImpl : public Base {
  int getVal() override { return DI::k_Val; }
};

我想问题零是这是否是已知/常见/正式模式,如果是,它的名字是什么?

一个常见的需求是扩展 Base 接口,比如 Inherited。任何 Inherited 对象仍应多态地用作 Base,但也应用作 Inherited,它可以定义其他方法。类似的东西:

struct Inherited : public Base {
  virtual int getotherVal() = 0;
};

问题在于在 BaseImpl<> 中重复使用 InheritedImpl<> 的实现。因为 InheritedImpl<> 需要从 InheritedBaseImpl<> 继承,所以我们遇到了 "dreaded dimond" 问题,所以我们必须使用虚拟继承。请参阅 godbolt 中的工作示例。

struct Base {
  virtual int getVal() = 0;
};

template <typename DI>
struct BaseImpl : public virtual Base {
  int getVal() override { return DI::k_Val; }
};

struct Inherited : public virtual Base {
  virtual int getotherVal() = 0;
};

template <typename DI>
struct InheritedImpl : public Inherited,public BaseImpl<DI> {
  int getotherVal() override { return DI::k_OtherVal; }
};

void useBase(Base& base) {
    std::cout << "getVal: " << base.getVal() << std::endl;
}

void useInherited(Inherited& inherited) {
    std::cout << "getotherVal: " << inherited.getotherVal() << std::endl;
}

struct DI {
  static constexpr int k_Val = 1;
  static constexpr int k_OtherVal = 2;
};

int main() {
  auto base = std::make_unique<BaseImpl<DI>>();
  auto inherited = std::make_unique<InheritedImpl<DI>>();

  useBase(*base);
  useBase(*inherited);
  useInherited(*inherited);
}
getVal: 1
getVal: 1
getotherVal: 2

因为 issues with virtual inheritance,如果可能的话,我想避免在这里使用它。在这种情况下有其他选择吗?这可能是代码异味吗?任何架构建议?

解决方法

基本模式是:

struct Base{
  virtual int count()const=0;
};
template<class X,class B=Base>
struct CountImpl:B{
   int count()const final{ return X::count; }
};

现在我们可以 CountImpl<Foo,Extended> 对继承进行变基。

可以完成更高级的东西,包括插件方面等。在较简单的情况下这是不值得的,应该避免确实需要的复杂情况。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。