可扩展的基类方法?

时间:2015-07-31 07:01:27

标签: c++ templates

(我不确定这是属于模板还是虚函数还是属于两者之一。)

假设我们有一个只有两个值x,y的基类(比如tuple2)。 这个基类有一个名为" norm"在x,y上运行,例如(sqrt(x x + y y))。

现在我们想扩展这个类:

struct tuple2
{
   double x,y;
   double norm ()                       {return sqrt(x*x+y*y);}
   double dotProd (const tuple2& other) {return other.x*x+other.y*y;}
}

struct tuple3:public tuple2
{
   double z;
}

tuple3添加了一个变量。

是否可以定义基类方法,以便它可以处理x,y和z而不会重载?

功能不相同,但具有相同的模式。我想我正在寻找一种扩展变量数量的模板,而不仅仅是类型?

3 个答案:

答案 0 :(得分:1)

我建议使用免费功能。您可以read an article认为免费功能通常优先于成员函数。

double dotProd(const tuple2 &t1, const tuple2 &t2){
    return t1.x * t2.x + t1.y * t2.y;
}

double dotProd(const tuple3 &t1, const tuple3 &t2){
    return t1.x * t2.x + t1.y * t2.y + t1.z * t2.z;
}

易于编写,易于理解,易于扩展且性能良好。

我在C ++中使用继承扩展类并没有太大成功,也不推荐它。

答案 1 :(得分:0)

抽象可以通过继承和使用模板获得。但我将如何决定取决于以下规则。 如果广义类要由具有共同操作的对象使用,请使用模板 如果属性和操作都是常见的(类似对象),请执行继承。

是否可以定义基类方法,以便它可以处理x,y和z而不会重载?

根本就没有!!!  如果函数具有相同的模式,我将更喜欢模板特化。

注意:这些是我的看法我真的很感激能够纠正这些错误的人。

答案 2 :(得分:0)

我想你需要看看这个:

http://www.linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_106.html

以您的示例为例:

template <size_t N>
struct tuple
{
    std::array<double, N> elements;
    double norm()
    {
        double n(0.);
        for ( std::size_t i(0) ; i < N ; ++i )
            n += std::pow(elements[i], 2.);
        return std::pow(n, 0.5);
    }
};

我理解你的点和其他特定功能的问题......你必须选择是否可以在类内部声明函数。如果你想在内部放置一个特定的函数(交叉产品仅适用于N == 3),请使用enable_if,如下所示:

template<bool B, typename T = void>
using Enable_if = typename std::enable_if<B, T>::type;

template <size_t N>
struct tuple
{
    std::array<double, N> elements;
    double norm()
    {
        double n(0.);
        for ( std::size_t i(0) ; i < N ; ++i )
            n += std::pow(elements[i], 2.);
        return std::pow(n, 0.5);
    }
    template<class THIS = tuple<N>,
         typename = Enable_if<std::is_same<THIS, tuple<3>>::value>>
    tuple<3> getCrossProduct(const tuple<3>& other);
};

template <std::size_t N>
template<class THIS, typename>
tuple<3> tuple<N>::getCrossProduct(const tuple<3>& other)
{/*...*/}

如果在类中,可以执行许多操作,除了定义具有相同参数列表的相同函数的两个版本(具有不同的N)。

我希望这对您的需求有所帮助。