我对模板的实际使用很陌生,所以我有以下设计问题。
我正在设计派生自抽象基类Bunch2d
的类Bunch4d
和Bunch
:
class Bunch {virtual void create()=0;};
class Bunch2d : public Bunch {void create();};
class Bunch4d : public Bunch {void create();};
班级Bunch
将包含deque
的容器,vector
或Particle
(请参阅this question: Choice of the most performant container (array)):
typedef Blitz::TinyVector<double,DIMENSIONS> Particle;
你因此看到我的问题:Bunch
必须包含这个容器,因为我的一堆“基础”操作是“维度独立”(例如“容器大小”,“透明容器”等。),所以我认为容器属于基类(“Bunch'有'容器'。
但是这个容器必须知道派生类的维度(2或4)。
所以我的想法是使用模板化的基类为typedef提供容器的正确尺寸:
enum Dimensions {TwoDimensions = 2, FourDimensions = 4, SixDimensions = 6};
template<Dimensions D> class Bunch
{
protected:
typedef Blitz::TinyVector<double,D> Particle;
std::deque<Particle> particles_store;
public:
virtual void create() = 0;
virtual ~Bunch();
};
class Bunch2d : public Bunch<TwoDimensions>
{
public:
~Bunch2d();
void create();
};
class Bunch4d : public Bunch<FourDimensions>
{
public:
~Bunch4d();
void create();
};
你能否就这个设计给我你的意见?它是否正确使用模板? OO概念的有效性如何?有模板化的基类?
感谢您的帮助/回答/意见。
答案 0 :(得分:2)
只有一个注释:不同的模板实例(即参数中具有不同类型的模板类)具有不同的类型,因此不是单个基类。
如果您需要多态性,则需要在设计中添加一个图层:
class Bunch
{
public:
virtual void create() = 0;
virtual ~Bunch();
};
template <Dimensions D>
class TBunch: public Bunch
{
private:
typedef Blitz::TinyVector<double,D> Particle;
std::deque<Particle> mParticles;
};
class Bunch2d : public TBunch<TwoDimensions>
{
public:
~Bunch2d();
void create();
};
另一方面,protected
应该禁止使用属性。
问题是耦合问题,因为protected
将属性/方法暴露给未知数量的类,它与public
没有区别,因为不可能可靠地说明将影响多少方法通过改变实施方式。
对于方法,它是可以接受的,因为方法可以保持向后兼容(有时以某些技巧/等等为代价......但仍然如此)。
对于属性,这是不可接受的,因为属性是实现细节,而不是接口,并且无法使更改向后兼容。
因此,我建议您不要使用protected
作为属性。在这种特殊情况下,最好将访问因素考虑在模板类中mParticles
,而不暴露底层实现。
小提示:如果你不能在deque
和vector
之间切换而不会破坏持有它们的类,那么你就会遇到设计问题。
答案 1 :(得分:2)
然后你就失去了在运行时指向Bunch类指向Bunch2d或Bunch4d对象的能力,并通过该指针以多态方式操纵这些对象。如果你不放松它是很重要的,不要让基类模板化。否则,在这里完全没有虚拟函数和抽象基类,所以我建议只使用模板。
答案 2 :(得分:0)
首先,Bunch<TwoDimensions>
和Bunch<FourDimensions>
是完全不相关的类,就继承而言。因此,Bunch2d
和Bunch4d
没有共同的基类!
如果这对您来说是一个问题,您将不得不取消模板,并在运行时参数化{。}}。