Ответ 1
Разбивка вашей декларации и ее членов несколько замусорена:
Удалите typedef
typedef
не требуется, не требуется для объявлений class/struct в С++. Ваши члены не знают об объявлении pos
как написано, что является основой вашего текущего сбоя компиляции.
Измените это:
typedef struct {....} pos;
Для этого:
struct pos { ... };
Удалить посторонние строки
Вы объявляете и определяете свои операторы-члены в самом определении класса. Ключевое слово inline
не требуется, пока ваши реализации остаются в их текущем местоположении (определение класса)
Возвращает ссылки на *this
, где это необходимо
Это связано с обилием копий конструкций в рамках вашей реализации, которые не должны быть сделаны без веских оснований для этого. Это связано с идеологией выражения:
a = b = c;
Это присваивает c
до b
, а результирующее значение b
затем присваивается a
. Это не эквивалентно следующему коду, вопреки тому, что вы думаете:
a = c;
b = c;
Следовательно, ваш оператор присваивания должен быть реализован как таковой:
pos& operator =(const pos& a)
{
x = a.x;
y = a.y;
return *this;
}
Даже здесь это не нужно. Оператор присваивания копий по умолчанию сделает это бесплатно (и код! Woot!)
Примечание: бывают случаи, когда вышеизложенное следует избегать в пользу идиома copy/swap. Хотя это не требуется для этого конкретного случая, это может выглядеть так:
pos& operator=(pos a) // by-value param invokes class copy-ctor
{
this->swap(a);
return *this;
}
Затем реализуется метод подкачки:
void pos::swap(pos& obj)
{
// TODO: swap object guts with obj
}
Вы делаете это, чтобы использовать класс copy-ctor для создания копии, а затем используйте безопасную замену для выполнения обмена. В результате входящая копия отбрасывает (и уничтожает) ваш объект старыми кишками, в то время как ваш объект принимает на себя право собственности. Подробнее здесь идиома copy/swap, а также плюсы и минусы в ней.
Передавать объекты по ссылке const при необходимости
Все ваши входные параметры для всех ваших членов в настоящее время создают копии того, что передается при вызове. Хотя для такого кода может быть тривиальным, это может быть очень дорого для более крупных типов объектов. Пример приведен здесь:
Измените это:
bool operator==(pos a) const{
if(a.x==x && a.y== y)return true;
else return false;
}
К этому: (также упрощенный)
bool operator==(const pos& a) const
{
return (x == a.x && y == a.y);
}
Никаких копий ничего не сделано, что приводит к более эффективному коду.
Наконец, отвечая на ваш вопрос, в чем разница между функцией-членом или оператором, объявленным как const
, и тем, что нет?
A const
member объявляет, что вызов этого элемента не будет изменять базовый объект (изменяемые декларации не выдерживают). Только const
функции-члены могут быть вызваны против объектов const
или const
ссылок и указателей. Например, ваш operator +()
не изменяет ваш локальный объект и поэтому должен быть объявлен как const
. Ваш operator =()
явно изменяет локальный объект, и поэтому оператор должен не быть const
.
Резюме
struct pos
{
int x;
int y;
// default + parameterized constructor
pos(int x=0, int y=0)
: x(x), y(y)
{
}
// assignment operator modifies object, therefore non-const
pos& operator=(const pos& a)
{
x=a.x;
y=a.y;
return *this;
}
// addop. doesn't modify object. therefore const.
pos operator+(const pos& a) const
{
return pos(a.x+x, a.y+y);
}
// equality comparison. doesn't modify object. therefore const.
bool operator==(const pos& a) const
{
return (x == a.x && y == a.y);
}
};
EDIT OP хотел посмотреть, как работает цепочка операторов присваивания. Ниже показано, как это:
a = b = c;
Это эквивалентно этому:
b = c;
a = b;
И это не всегда приравнивается к этому:
a = c;
b = c;
Пример кода:
#include <iostream>
#include <string>
using namespace std;
struct obj
{
std::string name;
int value;
obj(const std::string& name, int value)
: name(name), value(value)
{
}
obj& operator =(const obj& o)
{
cout << name << " = " << o.name << endl;
value = (o.value+1); // note: our value is one more than the rhs.
return *this;
}
};
int main(int argc, char *argv[])
{
obj a("a", 1), b("b", 2), c("c", 3);
a = b = c;
cout << "a.value = " << a.value << endl;
cout << "b.value = " << b.value << endl;
cout << "c.value = " << c.value << endl;
a = c;
b = c;
cout << "a.value = " << a.value << endl;
cout << "b.value = " << b.value << endl;
cout << "c.value = " << c.value << endl;
return 0;
}
Выход
b = c
a = b
a.value = 5
b.value = 4
c.value = 3
a = c
b = c
a.value = 4
b.value = 4
c.value = 3