Подтвердить что ты не робот

Перегрузка операторов в структурах typedef (С++)

Я хочу создать структуру typedef под названием pos (из позиции), в которой хранятся координаты x и y. Я пытаюсь перегрузить некоторые операторы для этой структуры, но она не компилируется.

typedef struct {
    int x;
    int y;

    inline pos operator=(pos a) {
        x=a.x;
        y=a.y;
        return a;
    }

    inline pos operator+(pos a) {
        return {a.x+x,a.y+y};
    }

    inline bool operator==(pos a) {
       if (a.x==x && a.y== y)
          return true;
       else
          return false;
    }
} pos;

Я также хотел узнать разницу между этим:

inline bool operator==(pos a) {
    if(a.x==x && a.y== y)
       return true;
      else
       return false;
}

И это:

bool operator==(pos a) const {
      if(a.x==x && a.y== y)
         return true;
      else
         return false;
}
4b9b3361

Ответ 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

Ответ 2

Вместо typedef struct { ... } pos; вы должны делать struct pos { ... };. Проблема здесь в том, что вы используете имя типа pos до его определения. Переместив имя в начало определения структуры, вы можете использовать это имя в самом определении структуры.

Кроме того, шаблон typedef struct { ... } name; является C-ism и не имеет большого места в С++.

Чтобы ответить на ваш вопрос о inline, в этом случае нет никакой разницы. Когда метод определен в определении структуры/класса, он неявно объявляется встроенным. Когда вы явно указываете inline, компилятор эффективно игнорирует его, потому что метод уже объявлен inline.

(inline методы не будут вызывать ошибку компоновщика, если один и тот же метод определен в нескольких объектных файлах, а компоновщик будет просто игнорировать всех, кроме одного из них, при условии, что они являются одинаковыми реализациями. изменение поведения с помощью встроенных методов. В настоящее время они не влияют на решение компилятора относительно того, являются ли встроенные функции или нет, они просто облегчают возможность реализации функции во всех единицах перевода, что дает компилятору возможность встроить функцию, если она решает, что было бы полезно сделать это.)

Ответ 3

  • bool operator == (pos a) const {- этот метод не изменяет элементы объекта.
  • bool operator == (pos a) {- он может изменять элементы объекта.

Ответ 4

попробуйте следующее:

struct Pos{
    int x;
    int y;

    inline Pos& operator=(const Pos& other){
        x=other.x;
        y=other.y;
        return *this;
    }

    inline Pos operator+(const Pos& other) const {
        Pos res {x+other.x,y+other.y};
        return res;
    }

    const inline bool operator==(const Pos& other) const {
        return (x==other.x and y == other.y);
    }
 };