如何避免虚拟继承

时间:2013-02-12 11:22:26

标签: c++ templates multiple-inheritance

看起来像是一个很好的策略来组合像这样的对象(作为策略):

template<typename FluxType, typename SourceType>
class Model : public FluxType, public SourceType
{ };
//later in the code:
template<typename FluxType, typename SourceType>
class ConcreteModel : public Model<FluxType, SourceType>
{};

但是,FluxTypeSourceType是使用相同数据的类。所以我使用了虚拟继承:

class ConcreteModelProps{};
class ConcreteFlux : virtual public ConcreteModelProps
{};
class ConcreteFlux2 : virtual public ConcreteModelProps
{/*sligthly different implementation*/};
class ConcreteSource : virtual public ConcreteModelProps
{};
class DefaultSource2 
{/*no need for data*/};

这样我可以使用不同的ConcreteModelFluxType对象撰写SourceType

ConcreteModel<ConcreteFlux, DefaultSource2> /*or whatever*/.

事实是ConcreteModelProps中定义的数据与ConcreteModel密切相关。在我看来,我至少做错了什么。如何让这个设计变得更好?最好没有虚拟继承? thx,dodol

1 个答案:

答案 0 :(得分:1)

嗯,这很简单:你ConcreteFlux继承了ConcreteModelProps,违反了LISKOV Substitution Principle;所以你付出代价才是正确的。

现在,如果您外化数据,您可能正在使用更健全的模型。

template <typename FluxType, typename SourceType>
class Model {
public: 
    typedef typename FluxType::DataType DataType;
}; // class Model

template <typename M>
class ConcreteModel: public M {
}; // class ConcreteModel

然后:

class ConcreteFlux {
public:
    typedef ConcreteModelProps DataType;
};

class ConcreteSource {
public:
    typedef ConcreteModelProps DataType;
};

template <typename Data>
class DefaultSource {
    typedef Data DataType;
};

最后:

class ConcreteModel<Model<ConcreteFlux, ConcreteSource>> {};

当然,这意味着现在需要将ConcreteFluxConcreteSource的所有方法都传递给每个方法中的句柄ConcreteModelProps。这就是外化的意义所在。