在重用基本模板实现中替代虚拟继承
Alternative to virtual inheritance in re-using base template implementation
在我正在处理的一个项目中,我们使用了一种模式,其中我们有纯抽象 类 定义接口,以及可以使用不同模板参数实例化的模板实现,这些模板用于许多东西,包括依赖注入。类似于:
struct Base {
virtual int getVal() = 0;
};
template <typename DI>
struct BaseImpl : public Base {
int getVal() override { return DI::k_Val; }
};
我想第零个问题是这是否是一个 known/common/formal 模式,如果是,它的名字是什么?
一个经常出现的需求是扩展 Base
接口,比如 Inherited
。任何 Inherited
对象仍应具有多态功能,如 Base
,但也可作为 Inherited
,它可以定义其他方法。类似于:
struct Inherited : public Base {
virtual int getOtherVal() = 0;
};
问题在于在 InheritedImpl<>
中重新使用 BaseImpl<>
的实现。因为 InheritedImpl<>
需要继承 Inherited
和 BaseImpl<>
我们 运行 到 "dreaded dimond" problem, so we have to use virtual inheritance. See working example in 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>
对继承进行变基。
可以完成更高级的东西,包括插件方面等。在更简单的情况下,这是不值得的,应该避免确实需要它的复杂情况。
在我正在处理的一个项目中,我们使用了一种模式,其中我们有纯抽象 类 定义接口,以及可以使用不同模板参数实例化的模板实现,这些模板用于许多东西,包括依赖注入。类似于:
struct Base {
virtual int getVal() = 0;
};
template <typename DI>
struct BaseImpl : public Base {
int getVal() override { return DI::k_Val; }
};
我想第零个问题是这是否是一个 known/common/formal 模式,如果是,它的名字是什么?
一个经常出现的需求是扩展 Base
接口,比如 Inherited
。任何 Inherited
对象仍应具有多态功能,如 Base
,但也可作为 Inherited
,它可以定义其他方法。类似于:
struct Inherited : public Base {
virtual int getOtherVal() = 0;
};
问题在于在 InheritedImpl<>
中重新使用 BaseImpl<>
的实现。因为 InheritedImpl<>
需要继承 Inherited
和 BaseImpl<>
我们 运行 到 "dreaded dimond" problem, so we have to use virtual inheritance. See working example in 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>
对继承进行变基。
可以完成更高级的东西,包括插件方面等。在更简单的情况下,这是不值得的,应该避免确实需要它的复杂情况。