来自模板化基类的派生类

时间:2010-09-06 08:57:44

标签: c++ templates

我对模板的实际使用很陌生,所以我有以下设计问题。

我正在设计派生自抽象基类Bunch2d的类Bunch4dBunch

class Bunch {virtual void create()=0;};
class Bunch2d : public Bunch {void create();};
class Bunch4d : public Bunch {void create();};

班级Bunch将包含deque的容器,vectorParticle(请参阅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概念的有效性如何?有模板化的基类?

感谢您的帮助/回答/意见。

3 个答案:

答案 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,而不暴露底层实现。

小提示:如果你不能在dequevector之间切换而不会破坏持有它们的类,那么你就会遇到设计问题。

答案 1 :(得分:2)

然后你就失去了在运行时指向Bunch类指向Bunch2d或Bunch4d对象的能力,并通过该指针以多态方式操纵这些对象。如果你不放松它是很重要的,不要让基类模板化。否则,在这里完全没有虚拟函数和抽象基类,所以我建议只使用模板。

答案 2 :(得分:0)

首先,Bunch<TwoDimensions>Bunch<FourDimensions>是完全不相关的类,就继承而言。因此,Bunch2dBunch4d没有共同的基类!

如果这对您来说是一个问题,您将不得不取消模板,并在运行时参数化{。}}。