3

我正在尝试熟悉 C++ 中的运算符。我想我会用一个简单的向量加法来做到这一点。不幸的是,我似乎遇到了一些问题。我的班级定义如下:

#ifndef _MVEC_H_
#define _MVEC_H_

#include "Error.h" //I define things like throw(message) here, it works and is not the issue

class MVec {
        private:
                double vec[3];
        public:
                MVec();
                MVec(double &);
                MVec(double *);
                MVec(MVec &);
                MVec & operator=(MVec &);
                inline double & operator[](const int i);
                inline const double & operator[](const int i) const;
                MVec operator+(const MVec &) const;
                ~MVec();
};

MVec::MVec() {}

MVec::MVec(double &a) {
        for(int i = 0; i < 3; i++)
                vec[i] = a;
}

MVec::MVec(double *a) {
        for(int i = 0; i < 3; i++)
                vec[i] = *a++;
}

MVec::MVec(MVec &rhs) {
        for(int i = 0; i < 3; i++)
                vec[i] = rhs[i];
}

MVec & MVec::operator=(MVec &rhs) {
        if(this != &rhs)
                for(int i = 0; i < 3; i++)
                        vec[i] = rhs[i];

        return *this;
}

inline double & MVec::operator[](const int i) {
        #ifdef _CHECKBOUNDS_
        if(i < 0 || i >= 3)
                throw("Subscript out of bounds");
        #endif

        return vec[i];
}

inline const double & MVec::operator[](const int i) const {
        #ifdef _CHECKBOUNDS_
        if(i < 0 || i >= 3)
                throw("Subscript out of bounds");
        #endif

        return vec[i];
}

MVec MVec::operator+(const MVec &vec1) const {
        MVec ans;

        for(int i = 0; i < 3; i++)
                ans[i] = vec[i] + vec1[i];

        return ans;
}

MVec::~MVec() {
        delete[] vec;
}

#endif

[] 运算符似乎按预期工作。不幸的是,向量加法运算符没有。具体来说,当我运行代码时:

#include "Error.h"
#include "MVec.h"
#include <cstdlib>
#include <iostream>

int main(int argc, char *argv[]) {
        MVec a, b, c;
        a[0] = 1; a[1] = 2; a[2] = 3;
        b[0] = 5.9906; b[1] = 72.1139; b[2] = 83.1324;

        //c = a + b;

        std::cout << (a + b)[0] << std::endl;
        std::cout << (a + b)[1] << std::endl;
        std::cout << (a + b)[2] << std::endl;

        exit(0);
}

当我取消注释行 c = a + b; 我得到一个编译器错误:

'c = MVec::operator+(const MVec&) const(((const MVec&)((const MVec*)(& b))))'中的 'operator=' 不匹配

当我注释掉它时,我在第一个 std::cout 之后得到一个 glibc 检测到的错误。据推测,我在 operator+ 函数中创建的临时变量做错了。不幸的是,我(很)不够聪明,无法弄清楚是什么。对此的任何和所有见解都会非常有帮助。

4

3 回答 3

8

您需要在复制构造函数中const引用 toMVec以便能够将其与临时对象一起使用:

MVec(const MVec &);

这同样适用于赋值运算符,以及采用 a 的构造函数double

MVec(const double &); // or no reference, MVec(double);
MVec& operator=(const MVec& rhs);

您还应该delete [] vec从析构函数中删除 ,因为vec它不是动态分配的。这是 glibc 错误的可能原因。

现在,为了表达如

SomeVec = 1.0 + SomeOtherVec;

您需要将 声明operator+为非成员函数:

MVec operator+(const MVec& lhs, const MVec& lhs); 

这将允许在 LHS 和 RHS 上进行隐式转换。一般来说,将这些类型的运算符作为非成员函数是一个好主意,以保证 LHS 和 RHS 操作数之间的对称性。

另一方面,根本不允许隐式转换可能更有意义double。您可以通过制作相关的构造函数来实现这一点explicit

explicit MVec(double);
于 2012-11-19T19:55:20.670 回答
2

编译时错误很容易解释:您的赋值运算符需要一个非const引用作为参数,但您不能将非const引用绑定到临时变量,因为它是从您的operator+(). 一种天真的解决方法是让操作员const&取而代之。但是,您实际上根本不需要定义复制赋值运算符!编译器生成的复制构造、复制赋值和析构函数都很好。你可以删除它们,你会过得更好。

特别是删除析构函数也可以解决您的其他问题:您delete[]在析构函数中使用尚未分配的内存!你不应该这样做。也就是说,如果你修复了你的析构函数,它将是空的,也就是说,你也可以删除它。

于 2012-11-19T20:00:02.120 回答
1

MVec MVec::operator+(const MVec &vec1) const {
    MVec ans;

    for(int i = 0; i < 3; i++)
            ans[i] = vec[i] + vec1[i];

    return ans;
}

应使用 this 定义定义为非成员函数 MVec operator+(const MVec &vec1, const MVec &vec2) const。那么您需要修改以添加 vec1[i] + vec2[i],假设您的目标是添加两个向量中的每个值。

此外,您应该添加边界检查。如果任何一个向量的长度小于三,你就会崩溃。您应该添加到较短向量的长度,或者在所有长度都不相同时不添加它们。例子

 int loopVar = 0;
 if (vec1.length() > vec2.length())
     loopVar = vec2.length();
 else
     loopVar = vec1.length();

 for (int i = 0; i < loopVar; i++)
      ans[i] = vec1[i] + vec2[i];
于 2012-11-19T19:56:53.207 回答