从具有运算符重载的类派生

时间:2009-04-14 04:57:09

标签: c++ templates

我想创建一个类似于数学向量的类的集合,因此将对象乘以标量将每个字段乘以该ammount等等。事情是我希望字段具有实际名称,而不是被视为指数。

我实现这个的最初想法是创建一个带有重载的基类Rn,然后使用漂亮的名称创建派生类。像这样:

#include <iostream>
#include <algorithm>
using namespace std;

template<int N, class X=double>
struct Base{
    X xs[N];

    Base(){};

    Base(X *data){
        copy(data, data+N, xs);
    }

    Base operator*= (double d){
        for(int i=0; i<N; i++){
            xs[i] *= d;
        }
        return *this;
    }

    Base operator* (double d){
        Base answer = *this;
        answer *= d;
        return answer;
    }

    //also operators for +=, +, multiplication from left, maybe [] too
};

struct Derived : public Base<2>{
    Derived(double a, double b){
        foo() = a;
        bar() = b;
    }

    double &foo(){ return xs[0]; }
    double &bar(){ return xs[1]; }
};

int main()
{
    //this is OK:
    double data[2] = {0.0, 2.0};
    Base<2> b(data);
    b = b*17.0;

    cout << b.xs[0] << endl;

    //I can't do this:
    Derived x(0.0, 2.0);
    x = x*17.0;

    cout << x.foo() << endl;

    return 0;
}

每当我尝试使用需要复制的运算符时,我都会收到编译错误。 gcc给了我以下编译器错误:

teste.cpp: In function ‘int main()’:
teste.cpp:52: error: no match for ‘operator=’ in ‘x = x.Derived::<anonymous>.Base<N, X>::operator* [with int N = 2, X = double](1.7e+1)’
teste.cpp:31: note: candidates are: Derived& Derived::operator=(const Derived&)

我认为问题是重载函数处理无法转换为派生类的Base对象,因此我不能在派生类中使用它们。但是,我无法想出解决方案。有没有办法解决这个问题,还是应该采用完全不同的方法?

奖金问题:有什么方法可以使用std :: valarray来避免输入大量的操作符重载?

5 个答案:

答案 0 :(得分:3)

您的Base运算符(在本例中为*)可以接受Derived对象,但它们返回Base,不能在Derived default assignment operator中用作右侧操作数。解决此问题的最简单方法是向Derive添加一个赋值运算符,它将采用Base:

Derived& operator= (const Base<2>& other)

您必须将它添加到任何派生类,但实现相当简单(您可以在Base中使用void CopyOtherBase函数来执行复制,并让所有operator =调用它并返回* this)。 / p>

答案 1 :(得分:2)

我只会解决技术难题,而不是这是否是个好主意。

问题是Derived的operator *的结果是Base,而且operator = Derived(默认运算符=)不知道如何“吃掉”Base。

一个简单的解决方案是创建Derived的构造函数,该构造函数获取Base,并执行正确初始化所需的任何操作。这将允许将Base实时转换为Derived - 并且适用于期望Base的所有其他Derived运算符。

有些事情 -

Derived(const Base<2>& B) : Base<2>( B )
{
}

答案 2 :(得分:1)

我认为使用枚举或静态常量来命名字段会好得多

例如,static const int FIELD_NAME = 0;
      静态const int FIELD_NAME2 = 1;

比不同类型(模板)这样做。然后你可以使用std :: valarray或boost :: ublas :: vector / matrix类型来利用现有代码&amp;获得质量性能矢量操作来启动。

答案 3 :(得分:0)

模板元编程有一个有趣的想法,用数学向量解决这类问题,但可能无法解决你命名部分的问题。

David Abrahams,Aleksey Gurtovoy:C ++模板元编程:来自Boost and Beyond的概念,工具和技术,Addison-Wesley,ISBN 0-321-22725-5

答案 4 :(得分:0)

According to MSDN

  

除了以外的所有重载运算符   赋值(operator =)是继承的   通过派生类。

这可能是你的问题吗?