Я пытаюсь ознакомиться с операторами в 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; Я получаю ошибку компилятора:
нет совпадения для ‘operator =’ в ‘c = MVec :: operator + (const MVec&)
const (((const MVec&) ((const MVec *) (& б))))
Когда я комментирую это, я получаю ошибку, обнаруженную glibc после первого std :: cout. Предположительно, я делаю что-то не так с временной переменной, которую создаю в функции operator +. К сожалению, я не достаточно умна, чтобы понять что. Любое понимание этого было бы очень полезно.
Вам нужно взять const
ссылка на MVec
в вашем конструкторе копирования, чтобы иметь возможность использовать его с временными файлами:
MVec(const MVec &);
То же самое относится к оператору присваивания, и конструктор, принимающий 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);
Ошибка времени компиляции легко объясняется: ваш оператор присваивания ожидаетconst
ссылка в качестве аргумента, но вы не можете связать неconst
ссылка на временный, так как он возвращается из вашего operator+()
, Вид наивного исправления — заставить оператора взять const&
вместо. Однако на самом деле вам вообще не нужно определять оператор присваивания копии! Созданная компилятором конструкция копирования, назначение копирования и деструктор — все в порядке. Вы можете просто удалить их, и вам лучше.
Удаление деструктора, в частности, решит и другую проблему: вы delete[]
памяти в вашем деструкторе вы не распределили! Вы никогда не должны делать это. То есть, если вы исправите свой деструктор, он будет пустым, то есть вы можете просто удалить его.
этот
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 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];