模板化基类中的派生类
我对模板的实际使用颇为陌生,所以我有以下设计问题。从一个抽象基类Bunch
派生模板化基类中的派生类
我设计类Bunch2d
和Bunch4d
:
class Bunch {virtual void create()=0;};
class Bunch2d : public Bunch {void create();};
class Bunch4d : public Bunch {void create();};
类Bunch
将包含一个容器,一个deque
或vector
(见this question: Choice of the most performant container (array))的Particle
的:
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();
};
你能给我你的意见对这个设计?它会正确使用模板吗?面向对象概念的有效性如何?用模板化的基类?
感谢您的帮助/回答/意见。
有一个单一的说明:不同的模板实例(即参数中具有不同类型的模板类)具有不同的类型,因此不是单个基类。
如果你需要多态,你需要在你的设计中增加了一层:
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
之间切换,而不会超出拥有它们的类别,那么您有设计问题。
但问题是容器中包含的“粒子”(包含数百万个元素)必须由派生类操纵,并且将它设为私有并不是一个好主意,然后访问每个元素一。或者我可以使用函数指针或函数对象,并将它提供给TBunch,在TBunch中,方法将遍历元素并将函数应用于它们。它可以保持私密性。这是个好主意吗? – 2010-09-06 09:29:33
完全可以接受使用函数指针或谓词和'TBunch :: foreach'方法,是的。我不建议隐藏使用“粒子”的事实,只是为了隐藏你如何存储它们,这是一个实现细节。你也可以提供一个'ParticleIterator',封装'std :: deque
然后,您会失去在运行时将Bunch类的指针指向Bunch2d或Bunch4d对象并通过该指针多态操纵这些对象的能力。如果您不要忽略这一点很重要,请勿使基类模板化。否则,根本没有虚拟函数和抽象基类在这里,所以我建议只使用模板。
就开始而言,就继承而言,Bunch<TwoDimensions>
和Bunch<FourDimensions>
是完全无关的类。因此,Bunch2d
和Bunch4d
没有共同的基类!
如果这会对您造成问题,您将不得不废除模板,并在运行时参数化DIMENSIONS
。
不确定你的层次结构......在现实生活中,2D空间将是4D空间的特例,这是6D空间的一个特例。 – 2010-09-06 09:08:00
如果我在2d的情况下,我不想携带我的6维TinyVector例如。 – 2010-09-06 09:24:48