26

我正在创建一个双链表,并重载了 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 行是定义的最后一行,带有“}”。

4

4 回答 4

24

正是它所说的:运算符重载必须是成员函数。(在类内声明)

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

此外,从 = 返回 LHS 可能是个好主意,这样您就可以将它链接起来(如a = b = c) - 所以让它 list<T>& list<T>::operator=....

于 2009-05-15T23:40:34.233 回答
20

将该运算符放在您的类定义中。它必须是一个成员,因为它operator=很特别,无论如何你都不会通过将它写成非成员来获得什么。非会员运营商有两个重要的主要好处:

  • 运算符调用右侧和左侧的隐式转换
  • 无需了解班级的内部情况。功能可以实现为非会员非好友。

对于operator=,两者都不可用。分配给转换的临时结果没有意义,并且operator=在大多数情况下需要访问内部。此外,operator=如果您不提供,C++ 会自动提供一个特殊的(所谓的复制赋值运算符)。使operator=作为非成员重载成为可能会引入额外的复杂性,而显然没有实际收益,因此这是不允许的。

因此,更改您的代码,使其看起来像这样(这假设operator=不是复制赋值运算符,而是从 a 分配list<T>其他东西。这从您的问题中不清楚):

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

operator=a 再次返回对自身的引用是非常标准的。我建议你坚持这种做法。它对程序员来说看起来很熟悉,如果它void突然返回,可能会引起意外。

于 2009-05-15T23:44:32.663 回答
6

如果将运算符重载为成员函数,则应使用此模板:

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

需要注意的三点:

  1. 使用赋值运算符检查自赋值(如上);
  2. 参数应该是一个常量引用;和
  3. 将运算结果作为非常量引用返回,您可以在其中返回 *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;
}

这个返回一个 const 引用,所以你不能这样做:

(a + b) = c
于 2009-05-15T23:40:34.577 回答
-1

来自 C++ 标准,“二元运算符”:

“二元运算符应由具有一个参数的非静态成员函数或具有两个参数的非成员函数实现”

它希望您在类中将其定义为成员,或使其成为静态方法(在这种情况下,它应该采用两个参数(对于 lval 和 rval)。

于 2009-05-15T23:47:40.597 回答