2013-08-02 63 views
1

我试图实现的数据结构来管理n维矢量,其中n将不大于50。如何在一种情况下实现具有显着不同实现的类?

的问题是,n = 2的是具有相同的接口的特殊情况,但完全不同的实现。我怎样才能实现这个?

我正考虑Ñ模板参数和:

  1. 使对于n = 2
  2. Copypaste一个模板偏特n的接口= 2
  3. 使用构建的数据结构工厂将有这种结构的原型实例化为n = 2,3,...,50

有没有更好的方法?如果我按照我的建议实施它,我应该注意什么?

回答

3

答案取决于n在编译时是已知还是只在运行时才知道。

如果n在编译时已知,那么部分模板规范就是要走的路(本着与实现std::vector<bool>是模板规范相同的精神)。

如果n只知道在运行时,可以实现一个State Pattern保持内部的一个对象,以你的向量执行的操作,使得它的两种实现方式,并隐藏矢量对象内部的指针,它的实例:

struct Vector; 

struct VectorOperations { 
    virtual void doOperation1(Vector& v) = 0; 
    virtual void doOperation2(Vector& v) = 0; 
}; 

struct VectorOperationsTwo: VectorOperations { 
    virtual void doOperation1(Vector& v); 
    virtual void doOperation2(Vector& v); 
} opsTwo; 

struct VectorOperationsThreeAndMore: VectorOperations { 
    virtual void doOperation1(Vector& v); 
    virtual void doOperation2(Vector& v); 
} opsThreeAndMore; 

class Vector { 
    VectorOperations *ops; 
public: 
    Vector(int size) { 
     ops = size == 2 ? (VectorOperations*)&opsTwo : &opsThreeAndMore; 
    } 
    void operation1() { 
     ops->doOperation1(); 
    } 
    void operation2() { 
     ops->doOperation2(); 
    } 
    friend class VectorOperationsTwo; 
    friend class VectorOperationsThreeAndMore; 
}; 

这个例子假设两个元素的向量和两个以上元素的向量将具有相同的数据成员,所以我做了opsTwoopsThreeAndMore共享。如果不是这种情况,您可以在构造函数内分配新的VectorOperationsTwoVectorOperationsThreeAndMore

+0

我实际上在这里指的是*策略模式*,因为一旦设置它不再改变。 *状态模式*指的是一种随着时间而演变的策略:它与一台状态机(从中继承它的名字)密切相关。 –

+0

@MatthieuM。那么,在这种情况下,它可能是一种策略或一种状态,取决于API的其他部分。如果大小是在构造函数中设置的,并且再也不会改变,这是一种策略;如果我们让创造者在创造后改变他们的规模,并相应地调整我们的战略目标,它就会成为一个国家。感谢编辑! – dasblinkenlight

3

IMO为特殊情况n = 2提供一个实现的工厂,对于所有其他情况提供不同实现是最简单和最优雅的实现方式。

+0

谢谢!现在我正在考虑什么应该是工厂返回类型? –

+1

它取决于类的层次结构。如果n = 2的特殊情况作为更一般类(n!= 2)的子类实现,那么通用类是返回类型。如果n = 2和n!= 2都是一个(可能是抽象的)超类的子类,那么这个超类就是返回类型。 –

1

我认为容器尺寸在运行时是已知的,所以基于teplate专业化的解决方案不起作用。

那么PIMPL成语呢?存储两个实现,一个用于一般情况,另一个用于特殊情况。

+1

N是这里的尺寸,而不是尺寸。 – MSalters

1

模板偏特。接口的共享部分可以从非模板化(或至少非专业化)的基类继承。

原因是数据的维度非常不是运行时变量,而是依赖于域。

相关问题