【问题标题】:Work around for being unable to make function templates virtual?解决无法使功能模板虚拟化的问题?
【发布时间】:2010-06-23 14:56:44
【问题描述】:

我有一个代表 n 元组的抽象类顶点。顶点的元素可以是任何类型:即,顶点的组件可以是 int、int、float 或其他类型。因为顶点可以有任意数量的维度,我正在考虑让这个类有一个像这样的组件设置器:

class vertex {
    public:
        template <class T>
        virtual void setComp(int componentnumber, T value) = 0;
};

当然,C++ 不允许虚函数模板。所以:我应该怎么做?我也不知道应该如何为顶点编写 getter。

谢谢。

【问题讨论】:

标签: c++ templates abstract-class


【解决方案1】:

嗯,通常情况下,您应该将顶点类型作为模板参数,以便正确存储它:

template<typename T, size_t NumAxes = 3>
class vertex {
    private:
        T comp[NumAxes];
};

在这种情况下,不需要虚拟方法,因为您可以使用 C++ 的类型转换来完成这项工作:

template<typename T, size_t NumAxes = 3>
class vertex {
public:
    template <typename U>
    void setComp(size_t index, U value) { comp[index] = static_cast<T>(value); }
private:
    T comp[NumAxes];
};

现在,如果您希望它是虚拟的,因为您希望子类能够弄乱事物(例如记录值的每次更改),您需要定义一个非模板函数:

template<typename T, size_t NumAxes = 3>
class vertex {
public:
    template <typename U>
    void setComp(size_t index, U value)
    { _setComp(index, static_cast<T>(value)); }
protected:
    T comp[NumAxes];
    virtual void _setComp(size_t index, T value) 
    { comp[index] = value; }
};

template<typename T, size_t NumAxes = 3>
class logged_vertex: public vertex<T, NumAxes> {
protected:
    virtual void _setComp(size_t index, T value);
};

template<typename T, size_t NumAxes = 3>
void logged_vertex<T, NumAxes>::_setComp(size_t index, T value)
{   cout << "Index " << index << " changed from " << comp[index];
    vertex<T, NumAxes>::_setComp(index, value);
    cout << " to " << comp[index] << endl;
}

【讨论】:

    【解决方案2】:

    这是 OO 和泛型编程的一种非常奇怪的组合。我认为你应该选择其中一个。

    将顶点类设为模板为“value”参数定义基类并派生自定义类型处理程序类。

    【讨论】:

      【解决方案3】:

      使用多态性而不是模板。

      或者限制你想要传递的类型,并进行重载。并增加维护成本。

      实施这些解决方案将涉及 boost::any 或 boost::variant 以节省您一些时间。

      【讨论】:

        【解决方案4】:

        Because the vertex can have an arbitrary number of dimensions - 不让它成为一个

        template<size_t N> class vector {
        
           private:
             boost::any elems[N];
        }
        

        然后避免通过模板混合运行时多态性和编译时多态性?或者,如果数量有限,则对任何可能的类型使用函数重载。

        virtual void setComp(int, float) = 0;
        virtual void setComp(int, bool) = 0;
        

        【讨论】:

        • 我记得曾经想要一个这样的设计,然后哭着为什么我不简单地把 n 做成一个成员变量......
        【解决方案5】:

        首先,我会问自己是否真的需要在运行时多态地访问顶点对象。例如,如果您需要能够拥有不同类型(double、int 等)的 vertex* 对象列表并以多态方式访问它们。

        在我看来,顶点是编译时多态性的典型案例(即template &lt;typename CoordinateType&gt; class vertex; 模板)。

        【讨论】:

        • 我什至会使用简单的数组 或等效的,但问题是关于虚拟模板,而不是这样的设计是否好。
        猜你喜欢
        • 2012-10-08
        • 2010-10-19
        • 2019-06-14
        • 2022-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        相关资源
        最近更新 更多