2013-02-12 101 views
1

似乎是一個很好的策略,撰寫我的對象是這樣的(如政策):如何避免虛擬繼承

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

這樣,我可以譜寫我ConcreteModel不同FluxTypeSourceType對象。

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

的事實是,在ConcreteModelProps中定義的數據密切相關的ConcreteModel。在我看來,我至少在做錯事。我怎樣才能使這個設計更好?最好沒有虛擬繼承? thx,dodol

+0

順便說一句,爲什麼[Smurf命名](http://www.codinghorror.com/blog/2012/07/new-programming-jargon.html)? – Kos 2013-02-12 11:25:04

+0

可能是[CRTP模式](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)可能有助於您的情況,因此您可以在不需要虛擬繼承的情況下混合使用各種實現。 – 2013-02-12 11:26:37

+0

@Kos thx,已更改 – dodol 2013-02-12 11:28:00

回答

1

嗯,很簡單:你違反了LISKOV Substitution PrincipleConcreteFlux繼承自ConcreteModelProps;所以只有你付出代價。

現在,如果你外部化了的數據,你可以使用一個更好的模型。

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他們的方法。這就是外化是關於。