Что означает "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 является последней строкой определения с "}".
Ответы
Ответ 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).