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

Что означает "operator = должен быть нестатический член"?

Я создаю список с двойной связью и перегрузил оператор =, чтобы сделать в списке равным другому:

template<class T>
void operator=(const list<T>& lst)
{
    clear();
    copy(lst);
    return;
}

но я получаю эту ошибку, когда пытаюсь скомпилировать:

container_def.h(74) : error C2801: 'operator =' must be a non-static member

Кроме того, если это помогает, строка 74 является последней строкой определения с "}".

4b9b3361

Ответ 1

Именно это и говорит: перегрузки операторов должны быть функциями-членами. (объявлено внутри класса)

template<class T>
void list<T>::operator=(const list<T>& rhs)
{
    ...
}

Также, вероятно, будет хорошей идеей вернуть LHS из =, чтобы вы могли связать его (например, a = b = c) - так что сделайте это list<T>& list<T>::operator=....

Ответ 2

Поместите этот оператор в определение вашего класса. Он должен быть членом, потому что operator= является особенным, и вы ничего не получите, написав его как не-член в любом случае. Оператор, не являющийся членом, имеет два важных основных преимущества:

  • Неявные преобразования правой и левой сторон вызова оператора
  • Не нужно знать о внутренних компонентах класса. Функция может быть реализована как не-член, не являющийся другом.

Для operator=, оба нельзя использовать. Присвоение временного результата преобразования не имеет смысла, а operator= в большинстве случаев потребуется доступ к внутренним элементам. Кроме того, специальный operator= автоматически предоставляется С++, если вы не предоставляете его (так называемый оператор копирования). Предоставляя возможность перегрузки operator=, поскольку не-член мог бы ввести дополнительную сложность, чтобы, по-видимому, никакой практической выгоды, и поэтому это недопустимо.

Так измените свой код так, чтобы он выглядел так (это предполагает, что operator= не является оператором присваивания копий, а назначает из list<T> что-то еще. Это не ясно из вашего вопроса):

class MyClass {
...
    template<class T>
    MyClass& operator=(const list<T>& lst)
    {
        clear();
        copy(lst);
        return *this;
    }
...
};

Довольно стандартно, что operator= снова возвращает ссылку на себя. Я рекомендую вам придерживаться этой практики. Он будет выглядеть знакомым программистам и может вызвать неожиданности, если он вернет void внезапно.

Ответ 3

Если вы перегружаете оператор как функцию-член, вы должны использовать этот шаблон:

class A {
  A& operator=(const A& other) {
    if (this != &other) {
      ...
    }
    return *this;
  }
}

Три примечания:

  • Проверьте самоопределение с оператором присваивания (как указано выше);
  • Аргумент должен быть ссылкой на константу; и
  • Возвращает результат операции как неконстантную ссылку, в которой вы возвращаете * это, чтобы разрешить цепочку операторов.

Вы также можете перегрузить оператор, открытый для класса. Это не относится к этому примеру, потому что вы не можете сделать это с помощью оператора присваивания, но это стоит отметить, потому что во многих случаях оно превосходит функции-члены. Типичная форма:

class A {
  friend const A& operator+(const A& a, const A& b);
  ...
}
const A& operator+(const A& a, const A& b) {
  A& ret = ...
  return ret;
}

Это возвращает ссылку на константу, поэтому вы не можете этого сделать:

(a + b) = c

Ответ 4

Из стандарта С++ "Бинарные операторы":

"Двоичный оператор должен быть реализован либо нестатической функцией-членом с одним параметром, либо не-членной функцией с двумя параметрами"

Он хочет, чтобы вы определяли это в классе, как член, или делали его статическим методом (в этом случае он должен принимать два параметра (как для lval, так и для rval).