代码之家  ›  专栏  ›  技术社区  ›  bjskishore123

为什么不能使用非成员函数重载赋值运算符?

  •  27
  • bjskishore123  · 技术社区  · 14 年前

    可以使用成员函数而不是非成员函数重载赋值运算符 friend 功能:

    class Test
    {
        int a;
    public:
        Test(int x)
            :a(x)
        {}
        friend Test& operator=(Test &obj1, Test &obj2);
    };
    
    Test& operator=(Test &obj1, Test &obj2)//Not implemented fully. just for test.
    {
        return obj1;
    }
    

    它会导致此错误:

    为什么不能 函数用于重载赋值运算符?编译器允许重载其他运算符,如 += -= 使用 朋友 . 支持的内在问题/局限是什么 operator= ?

    9 回复  |  直到 9 年前
        1
  •  29
  •   Billy ONeal IS4    14 年前

    因为默认的 operator= 操作员= 永远不会有人打电话来。

    编辑:这个答案是回答

    支持=运算符的固有问题/限制是什么?

    问题的一部分。这里的其他答案引用了标准中说你做不到的部分,但这很可能是 为什么? 标准的那一部分是这样写的。

        2
  •  36
  •   AnT stands with Russia    9 年前

    首先,应该注意,这与作为 明确地。它实际上是作为成员函数或作为非成员(独立)函数实现复制分配。这个独立的函数是否是一个朋友是完全不相关的:它可能是,也可能不是,这取决于它想在类中访问什么。

    现在,这个问题的答案在D&E手册中给出了( The Design and Evolution of C++ ). 原因是编译器总是声明/定义类的成员复制赋值运算符(如果您没有声明自己的成员复制赋值运算符)。

    如果该语言还允许将copy assignment operator声明为独立(非成员)函数,那么您可能会得到以下结果

    // Class definition
    class SomeClass {
      // No copy-assignment operator declared here
      // so the compiler declares its own implicitly
      ...
    };
    
    SomeClass a, b;
    
    void foo() {
      a = b;
      // The code here will use the compiler-declared copy-assignment for `SomeClass`
      // because it doesn't know anything about any other copy-assignment operators
    }
    
    // Your standalone assignment operator
    SomeClass& operator =(SomeClass& lhs, const SomeClass& rhs);
    
    void bar() {
      a = b;
      // The code here will use your standalone copy-assigment for `SomeClass`
      // and not the compiler-declared one 
    }
    

    如上面的例子所示,复制赋值的语义将在翻译单元的中间发生变化-在声明独立运算符之前,编译器的版本将被使用。在声明之后,将使用您的版本。程序的行为将根据放置独立副本分配运算符声明的位置而改变。

    这被认为是不可接受的危险(它是),所以C++不允许拷贝赋值操作符被声明为独立函数。

    确实,在您的特定示例中,碰巧使用 朋友 函数,运算符在类定义中很早就声明了(因为这就是声明friends的方式)。所以,在您的情况下,编译器当然会立即知道您的运算符的存在。然而,从C++语言的角度来看,一般问题与朋友功能无关。从C++语言的观点来看,它是关于成员函数与非成员函数的,并且由于上面描述的原因,完全禁止复制成员的非成员过载。

        3
  •  8
  •   Chubsdad    14 年前

    $13.5.3-“赋值运算符应由一个非静态成员函数实现,该函数只有一个参数。 因为如果用户没有声明,则会为类隐式声明copy assignment operator=运算符(12.8),因此派生类的copy assignment operator始终隐藏基类赋值运算符。”

        4
  •  7
  •   Armen Tsirunyan    13 年前

    因为有些运算符必须是成员。这些操作员是:
    operator[]
    operator=
    operator()
    operator->

    和类型转换运算符,如 operator int .

    尽管有人可以解释为什么operator=必须是成员,但他们的论点不能应用于列表中的其他人,这使我相信“为什么”的答案是“仅仅因为”。

    高温高压

        5
  •  3
  •   Bart van Ingen Schenau    14 年前

    operator= 是一个特殊的成员函数,如果您不自己声明,编译器将提供它。因为这个特殊的地位 操作员= ro要求它是成员函数是有道理的,所以不可能同时存在编译器生成的成员 操作员= 操作员= 也不可能在两者之间做出选择。

        6
  •  1
  •   sbi    14 年前

    为什么friend函数不能用于重载赋值运算符?

    简短回答: 只是因为 .

    稍微长一点的答案是:语法就是这样固定的。几个操作员 必须是成员函数 . 赋值运算符是,

        7
  •  0
  •   Daniel Hanrahan    12 年前

    目的 operator= 是对当前对象的赋值操作。然后,LHS或左值是同一类型的对象。

    考虑一个LHS是整数或其他类型的情况。这个案子是由 operator int() 或相应的 operator T() 功能。因此,已经定义了LHS的类型,但不是成员 操作员= 函数可能会违反此规则。

    因此避免了。

        8
  •  0
  •   Nitin Gautam    9 年前

    因为有 已经是“=”的隐式运算符重载函数 在课堂上做 浅拷贝 . 所以即使你使用了一个friend函数 正如我们所做的任何调用都将调用隐式浅复制方法,而不是重载的friend函数。

        9
  •  0
  •   Community CDub    7 年前

    此职位适用于C++ 11

    为什么会有人想要一个非会员 operator= 操作员= 则可以使用以下代码:

    Test const &ref = ( Test() = something ); 
    

    Test& operator=(Test &obj1, Test obj2)
    

    因为现在prvalue Test() obj1 . 事实上,这个签名将强制我们永远不返回悬挂引用(当然,除非我们提供了一个悬挂引用),函数总是返回一个“有效”的左值,因为它强制使用左值调用。

    但是,在C++ 11中,现在有一种方法指定成员函数只能在LValk上调用,因此通过编写成员函数可以实现相同的目标:

    Test &operator=(Test obj2) &
    //                        ^^^
    

    现在,上面带有悬挂引用的代码将无法编译。


    注意。 操作员= 右边应该是value或const引用。在实现 copy and swap idiom