为什么赋值操作符必须重载为成员函数

时间:2022-10-27 17:49:12
RT,为什么[]、()、->、=这几个运算符必须重载为成员函数?

39 个解决方案

#1


谁说必须重载的?
你不用,就不重载呗

至于你想用又不想重载——你不写重载函数编译器怎么知道你想用这些操作符干什么?你用心灵感应能力告诉它吗?

#2


看不懂你准备干啥?不重载成成员函数,你准备重载成全局函数?

#3


出于正常语法习惯的考虑

#4


必须俩字有点不妥……

#5


= 是因为深浅拷贝的原因。。
[] () ->这几个。。不知道

#6


引用 3 楼  的回复:
出于正常语法习惯的考虑

但是这几个操作符重载为全局函数会报错,不像重载输入输出操作符,输入输出操作符重载为全局函数只是使用上不方便,但是不会报错。

#7


引用 1 楼  的回复:
谁说必须重载的?
你不用,就不重载呗

至于你想用又不想重载——你不写重载函数编译器怎么知道你想用这些操作符干什么?你用心灵感应能力告诉它吗?

我无语,我说的是必须重载为,不是必须重载!!看清楚没??

#8


引用 2 楼  的回复:
看不懂你准备干啥?不重载成成员函数,你准备重载成全局函数?

我问的是为什么必须重载为成员函数?照你的意思是说所有的运算符必须重载为成员函数了??

#9


想用就重载

#10


引用 4 楼  的回复:
必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

#11


引用 9 楼  的回复:
想用就重载

难道我描述的有问题??我是说这几个为什么必须重载为成员函数。而不是什么需不需要重载??你想用当然要重载,这不是废话吗?除非编译器合成的=是你想要的。

#12


引用 5 楼  的回复:
= 是因为深浅拷贝的原因。。
[] () ->这几个。。不知道

深浅拷贝应该不用限制成为成员函数吧,这个我也不确定。。。

#13


1、重载操作符没必要一定是成员函数,还可以是友元函数。

2、重载操作符函数为成员函数主要是你需要操作类内部的成员,
必须是成员函数或友元函数才行。

3、至于由深浅拷贝的原因要使其成为成员函数,这个不知道。

4、如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。

如果运算符被重载为类的成员函数,那么一元运算符没有参数,二元运算符只有一个右侧参数,因为对象自己成了左侧参数。

从语法上讲,运算符既可以定义为全局函数,也可以定义为成员函数。文献[Murray , p44-p47]对此问题作了较多的阐述,并总结了表8-4-1的规则。



运算符
规则

所有的一元运算符
建议重载为成员函数

= () [] ->
只能重载为成员函数

+= -= /= *= &= |= ~= %= >>= <<=
建议重载为成员函数

所有其它运算符
建议重载为全局函数

第四点来自  http://shake863.iteye.com/blog/213590

希望对你有所帮助。

#14


引用 13 楼  的回复:
1、重载操作符没必要一定是成员函数,还可以是友元函数。

2、重载操作符函数为成员函数主要是你需要操作类内部的成员,
必须是成员函数或友元函数才行。

3、至于由深浅拷贝的原因要使其成为成员函数,这个不知道。

4、如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。

如果运算符被重载为类的成员函数,那么一元运算符没有参数,二……


恩,这些都了解,但是还是没涉及到几个必须重载为成员的原因。。

#15


引用 10 楼  的回复:
引用 4 楼  的回复:

必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

不可能 你太扯了…… 

#16


引用 15 楼  的回复:
引用 10 楼  的回复:

引用 4 楼  的回复:

必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

不可能 你太扯了……

额,这个你试一下不就知道了吗?

#17


引用 15 楼  的回复:
引用 10 楼  的回复:

引用 4 楼  的回复:

必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

不可能 你太扯了……

这个你试一下就知道了。。。=是不可以,其他几个我没试。

#18


引用 6 楼  的回复:
引用 3 楼  的回复:

出于正常语法习惯的考虑

但是这几个操作符重载为全局函数会报错,不像重载输入输出操作符,输入输出操作符重载为全局函数只是使用上不方便,但是不会报错。

错了,输入输出操作符是重载为成员函数使用起来不方便。但是<<、>>还是可以重载从全局函数的,=、[]那几个就只能重载成成员函数,这是什么原因?

#19


简单地说,C++标准规定要这样使用,但为什么要这样规定,请看下面:

1:对于赋值操作符(=)--比较特别,因为任何类如果不提供显示的拷贝赋值(即重载=),则编译器会隐式地提供一个。这样的话,如果你再通过友元声明,进行全局的定义会造成调用二义性(即使允许,编译也会出错)。

2:对于所有楼主提到的操作符(=,[],(),->),只能声明为成员函数是为了避免不合法的书写通过编译(这是推测出的原因,更深层的可能要研究 C++ 的设计了)。这涉及到 C++ 中类型的隐式转换。下面通过代码例子说明:

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend bool operator<(const X& x1, const X& x2) { return true; } // 只是测试,无意义
};

class Y 
{
public:
    Y(){}
    Y(int){} // int 类型可以被隐式转换成 Y
    bool operator<(const Y& y) const { return true; } // 只是测试,无意义
};

int main()
{
    X x;
    if(1 < x) // 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数
    {}

    Y y;
    if(1 < y) // 不合法,使用成员重载函数,函数的第一个参数是 const *this,1 不能被隐式转换
    {}

    return 0;
}
// 注:编译的时候可以通过注释掉不同的代码来查看错误(即合法性),后面解释不能作为友元全局重载的原因

由上面的代码可以知道,如果将 =,[],(),-> 进行友元全局重载,那么就会出现 1=x; 1[x]; 1->x; 1(x); 这样的合法语句(起码编译器认为这些是合法的)--参考代码中的 if(1<x) 合法的片段,但显然这些是需要避免的,当然这些不是我们程序员的责任,应该有语言的设计者来实现,所以,就……。

希望楼主可以明白,Good Luck!

#20


引用 19 楼  的回复:
简单地说,C++标准规定要这样使用,但为什么要这样规定,请看下面:

1:对于赋值操作符(=)--比较特别,因为任何类如果不提供显示的拷贝赋值(即重载=),则编译器会隐式地提供一个。这样的话,如果你再通过友元声明,进行全局的定义会造成调用二义性(即使允许,编译也会出错)。

2:对于所有楼主提到的操作符(=,[],(),->),只能声明为成员函数是为了避免不合法的书写通过编译(这是推测出……

那对复合运算符来说,比如class X中把+=重载为友元,不也是会出现1+=x;这样的语句吗?

#21


@lZ
嗯,复合运算符确实合法,查了很久,还真没找到合理的原因,贴个测试代码,期待大神出现啊

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend const X& operator+=(const X& x1, const X& x2) { return x1; } // 只是测试,无意义
};

int main()
{
    X x;
    1 += x;// 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数

    return 0;
}


楼主和我,Good Luck!

#22


为了让它们有原本的意义。

#23


operator=是特殊成员函数,至于像[]标准规定:operator[] shall be a non-static member function with exactly one parameter

#24


引用 22 楼  的回复:
为了让它们有原本的意义。

能不能详细解释下~~

#25


引用 23 楼  的回复:
operator=是特殊成员函数,至于像[]标准规定:operator[] shall be a non-static member function with exactly one parameter

恩。但是标准这样规定是基于什么原因??

#26


太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊

#27


可以是全局的,可以在类中声明为友元,也可以不声明为友元~
只是有一点,如果不声明为友元,类中的成员你不可以用,所以一般都在类中声明为类的友元运算符重载~

#28


有本书 rob murray 写的《C++ strategies&tactics》page47

#29


有些东西,只是语言创造者一时审美观的直觉反应,不需要理由。
不要太钻牛角尖了,就是一个规定而已。

#30


引用 26 楼  的回复:
太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊

你到底想要表达什么意思??

#31


引用 29 楼  的回复:
有些东西,只是语言创造者一时审美观的直觉反应,不需要理由。
不要太钻牛角尖了,就是一个规定而已。

好吧,我也觉得有点太钻牛角尖了。结贴。

#32


引用 30 楼  的回复:
引用 26 楼  的回复:

太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊

你到底想要表达什么意思??
我的意思就是   类的运算符重载是有目的的,最用对象是类;RT,如果赋值操作符不重载为成员函数,那意思就是普通函数。既然这样,先假设以后所有的赋值操作都会调用这个重载后的赋值操作符功能,那你认为这个假设会成立吗?肯定不成立啊。我的理解就是,重载为类成员,就是  操作符的特化,作用区域是有限的。

#33


如果赋值操作符可以作为全局函数重载的话,可能会出现表达错误的语句

int operator=(int a, integer b);
这样重载之后,语句
2 = a; 表述也是正确的,但是却是明显的语法错误
为了避免此类错误,需要将赋值操作符重载为成员函数
--------------------------------------------------
首先要知道,如果类中没有重载赋值操作符时,类会自动生成一个默认的赋值操作符。例如,有两个同类对象A和B,当你没有将赋值操作符重载,而进行 A=B 的操作时,编译器会自动调用赋值操作将B的数据成员拷贝到A中。
而如果你重载了一个全局的赋值操作符,那么编译器不知道是否还需要再自己合成一个赋值操作符,从而引发歧义。

#34


引用 26 楼  的回复:
太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊




运算符重载以后,其原有功能仍然保留

#35


引用 33 楼  的回复:
如果赋值操作符可以作为全局函数重载的话,可能会出现表达错误的语句

int operator=(int a, integer b);
这样重载之后,语句
2 = a; 表述也是正确的,但是却是明显的语法错误
为了避免此类错误,需要将赋值操作符重载为成员函数
--------------------------------------------------
首先要知道,如果类中没……

这个有道理

#36


引用 19 楼  的回复:
简单地说,C++标准规定要这样使用,但为什么要这样规定,请看下面:

1:对于赋值操作符(=)--比较特别,因为任何类如果不提供显示的拷贝赋值(即重载=),则编译器会隐式地提供一个。这样的话,如果你再通过友元声明,进行全局的定义会造成调用二义性(即使允许,编译也会出错)。

2:对于所有楼主提到的操作符(=,[],(),->),只能声明为成员函数是为了避免不合法的书写通过编译(这是推测出……

这个有道理

#37


顶19楼

2楼3楼神逻辑!你们是学编程的吗??体育老师教的么..

#38


引用 21 楼 kingxuke 的回复:
@lZ
嗯,复合运算符确实合法,查了很久,还真没找到合理的原因,贴个测试代码,期待大神出现啊

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend const X& operator+=(const X& x1, const X& x2) { return x1; } // 只是测试,无意义
};

int main()
{
    X x;
    1 += x;// 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数

    return 0;
}


楼主和我,Good Luck!


帖子有点早了,但是看到之后收获很多。我觉得 kingxuke 解释的很好,这样看来为了避免1+=x或者1=x之类的语句,是应该把=
写作成员函数而不是友元函数,多谢!

#39


引用 21 楼 kingxuke 的回复:
@lZ
嗯,复合运算符确实合法,查了很久,还真没找到合理的原因,贴个测试代码,期待大神出现啊

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend const X& operator+=(const X& x1, const X& x2) { return x1; } // 只是测试,无意义
};

int main()
{
    X x;
    1 += x;// 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数

    return 0;
}


楼主和我,Good Luck!


不过我倒有另外一个问题看,1被隐式转换为X类型后,系统应该是创造了一个临时的X类对象吧,然后调用+=的时候,x1就是这个临时对象的引用吧?那么返回x1之后岂不是“返回了一个临时变量的引用”了吗?

#1


谁说必须重载的?
你不用,就不重载呗

至于你想用又不想重载——你不写重载函数编译器怎么知道你想用这些操作符干什么?你用心灵感应能力告诉它吗?

#2


看不懂你准备干啥?不重载成成员函数,你准备重载成全局函数?

#3


出于正常语法习惯的考虑

#4


必须俩字有点不妥……

#5


= 是因为深浅拷贝的原因。。
[] () ->这几个。。不知道

#6


引用 3 楼  的回复:
出于正常语法习惯的考虑

但是这几个操作符重载为全局函数会报错,不像重载输入输出操作符,输入输出操作符重载为全局函数只是使用上不方便,但是不会报错。

#7


引用 1 楼  的回复:
谁说必须重载的?
你不用,就不重载呗

至于你想用又不想重载——你不写重载函数编译器怎么知道你想用这些操作符干什么?你用心灵感应能力告诉它吗?

我无语,我说的是必须重载为,不是必须重载!!看清楚没??

#8


引用 2 楼  的回复:
看不懂你准备干啥?不重载成成员函数,你准备重载成全局函数?

我问的是为什么必须重载为成员函数?照你的意思是说所有的运算符必须重载为成员函数了??

#9


想用就重载

#10


引用 4 楼  的回复:
必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

#11


引用 9 楼  的回复:
想用就重载

难道我描述的有问题??我是说这几个为什么必须重载为成员函数。而不是什么需不需要重载??你想用当然要重载,这不是废话吗?除非编译器合成的=是你想要的。

#12


引用 5 楼  的回复:
= 是因为深浅拷贝的原因。。
[] () ->这几个。。不知道

深浅拷贝应该不用限制成为成员函数吧,这个我也不确定。。。

#13


1、重载操作符没必要一定是成员函数,还可以是友元函数。

2、重载操作符函数为成员函数主要是你需要操作类内部的成员,
必须是成员函数或友元函数才行。

3、至于由深浅拷贝的原因要使其成为成员函数,这个不知道。

4、如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。

如果运算符被重载为类的成员函数,那么一元运算符没有参数,二元运算符只有一个右侧参数,因为对象自己成了左侧参数。

从语法上讲,运算符既可以定义为全局函数,也可以定义为成员函数。文献[Murray , p44-p47]对此问题作了较多的阐述,并总结了表8-4-1的规则。



运算符
规则

所有的一元运算符
建议重载为成员函数

= () [] ->
只能重载为成员函数

+= -= /= *= &= |= ~= %= >>= <<=
建议重载为成员函数

所有其它运算符
建议重载为全局函数

第四点来自  http://shake863.iteye.com/blog/213590

希望对你有所帮助。

#14


引用 13 楼  的回复:
1、重载操作符没必要一定是成员函数,还可以是友元函数。

2、重载操作符函数为成员函数主要是你需要操作类内部的成员,
必须是成员函数或友元函数才行。

3、至于由深浅拷贝的原因要使其成为成员函数,这个不知道。

4、如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。

如果运算符被重载为类的成员函数,那么一元运算符没有参数,二……


恩,这些都了解,但是还是没涉及到几个必须重载为成员的原因。。

#15


引用 10 楼  的回复:
引用 4 楼  的回复:

必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

不可能 你太扯了…… 

#16


引用 15 楼  的回复:
引用 10 楼  的回复:

引用 4 楼  的回复:

必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

不可能 你太扯了……

额,这个你试一下不就知道了吗?

#17


引用 15 楼  的回复:
引用 10 楼  的回复:

引用 4 楼  的回复:

必须俩字有点不妥……

这几个确实必须为成员函数,重载成友元会报错。

不可能 你太扯了……

这个你试一下就知道了。。。=是不可以,其他几个我没试。

#18


引用 6 楼  的回复:
引用 3 楼  的回复:

出于正常语法习惯的考虑

但是这几个操作符重载为全局函数会报错,不像重载输入输出操作符,输入输出操作符重载为全局函数只是使用上不方便,但是不会报错。

错了,输入输出操作符是重载为成员函数使用起来不方便。但是<<、>>还是可以重载从全局函数的,=、[]那几个就只能重载成成员函数,这是什么原因?

#19


简单地说,C++标准规定要这样使用,但为什么要这样规定,请看下面:

1:对于赋值操作符(=)--比较特别,因为任何类如果不提供显示的拷贝赋值(即重载=),则编译器会隐式地提供一个。这样的话,如果你再通过友元声明,进行全局的定义会造成调用二义性(即使允许,编译也会出错)。

2:对于所有楼主提到的操作符(=,[],(),->),只能声明为成员函数是为了避免不合法的书写通过编译(这是推测出的原因,更深层的可能要研究 C++ 的设计了)。这涉及到 C++ 中类型的隐式转换。下面通过代码例子说明:

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend bool operator<(const X& x1, const X& x2) { return true; } // 只是测试,无意义
};

class Y 
{
public:
    Y(){}
    Y(int){} // int 类型可以被隐式转换成 Y
    bool operator<(const Y& y) const { return true; } // 只是测试,无意义
};

int main()
{
    X x;
    if(1 < x) // 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数
    {}

    Y y;
    if(1 < y) // 不合法,使用成员重载函数,函数的第一个参数是 const *this,1 不能被隐式转换
    {}

    return 0;
}
// 注:编译的时候可以通过注释掉不同的代码来查看错误(即合法性),后面解释不能作为友元全局重载的原因

由上面的代码可以知道,如果将 =,[],(),-> 进行友元全局重载,那么就会出现 1=x; 1[x]; 1->x; 1(x); 这样的合法语句(起码编译器认为这些是合法的)--参考代码中的 if(1<x) 合法的片段,但显然这些是需要避免的,当然这些不是我们程序员的责任,应该有语言的设计者来实现,所以,就……。

希望楼主可以明白,Good Luck!

#20


引用 19 楼  的回复:
简单地说,C++标准规定要这样使用,但为什么要这样规定,请看下面:

1:对于赋值操作符(=)--比较特别,因为任何类如果不提供显示的拷贝赋值(即重载=),则编译器会隐式地提供一个。这样的话,如果你再通过友元声明,进行全局的定义会造成调用二义性(即使允许,编译也会出错)。

2:对于所有楼主提到的操作符(=,[],(),->),只能声明为成员函数是为了避免不合法的书写通过编译(这是推测出……

那对复合运算符来说,比如class X中把+=重载为友元,不也是会出现1+=x;这样的语句吗?

#21


@lZ
嗯,复合运算符确实合法,查了很久,还真没找到合理的原因,贴个测试代码,期待大神出现啊

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend const X& operator+=(const X& x1, const X& x2) { return x1; } // 只是测试,无意义
};

int main()
{
    X x;
    1 += x;// 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数

    return 0;
}


楼主和我,Good Luck!

#22


为了让它们有原本的意义。

#23


operator=是特殊成员函数,至于像[]标准规定:operator[] shall be a non-static member function with exactly one parameter

#24


引用 22 楼  的回复:
为了让它们有原本的意义。

能不能详细解释下~~

#25


引用 23 楼  的回复:
operator=是特殊成员函数,至于像[]标准规定:operator[] shall be a non-static member function with exactly one parameter

恩。但是标准这样规定是基于什么原因??

#26


太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊

#27


可以是全局的,可以在类中声明为友元,也可以不声明为友元~
只是有一点,如果不声明为友元,类中的成员你不可以用,所以一般都在类中声明为类的友元运算符重载~

#28


有本书 rob murray 写的《C++ strategies&tactics》page47

#29


有些东西,只是语言创造者一时审美观的直觉反应,不需要理由。
不要太钻牛角尖了,就是一个规定而已。

#30


引用 26 楼  的回复:
太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊

你到底想要表达什么意思??

#31


引用 29 楼  的回复:
有些东西,只是语言创造者一时审美观的直觉反应,不需要理由。
不要太钻牛角尖了,就是一个规定而已。

好吧,我也觉得有点太钻牛角尖了。结贴。

#32


引用 30 楼  的回复:
引用 26 楼  的回复:

太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊

你到底想要表达什么意思??
我的意思就是   类的运算符重载是有目的的,最用对象是类;RT,如果赋值操作符不重载为成员函数,那意思就是普通函数。既然这样,先假设以后所有的赋值操作都会调用这个重载后的赋值操作符功能,那你认为这个假设会成立吗?肯定不成立啊。我的理解就是,重载为类成员,就是  操作符的特化,作用区域是有限的。

#33


如果赋值操作符可以作为全局函数重载的话,可能会出现表达错误的语句

int operator=(int a, integer b);
这样重载之后,语句
2 = a; 表述也是正确的,但是却是明显的语法错误
为了避免此类错误,需要将赋值操作符重载为成员函数
--------------------------------------------------
首先要知道,如果类中没有重载赋值操作符时,类会自动生成一个默认的赋值操作符。例如,有两个同类对象A和B,当你没有将赋值操作符重载,而进行 A=B 的操作时,编译器会自动调用赋值操作将B的数据成员拷贝到A中。
而如果你重载了一个全局的赋值操作符,那么编译器不知道是否还需要再自己合成一个赋值操作符,从而引发歧义。

#34


引用 26 楼  的回复:
太简单的问题搞的这么复杂,“重载为”这个语义是谁用的?是类,重载就是改变它的作用特性呗。为什么必须重载为成员函数,因为被修改后的作用特性的作用对象是这个你关心的类。如果不是成员函数,相反就是普通函数,假设int a; a = 2;这个=号被重载了,再执行特定的作用特性,还会成功吗,肯定crash啊




运算符重载以后,其原有功能仍然保留

#35


引用 33 楼  的回复:
如果赋值操作符可以作为全局函数重载的话,可能会出现表达错误的语句

int operator=(int a, integer b);
这样重载之后,语句
2 = a; 表述也是正确的,但是却是明显的语法错误
为了避免此类错误,需要将赋值操作符重载为成员函数
--------------------------------------------------
首先要知道,如果类中没……

这个有道理

#36


引用 19 楼  的回复:
简单地说,C++标准规定要这样使用,但为什么要这样规定,请看下面:

1:对于赋值操作符(=)--比较特别,因为任何类如果不提供显示的拷贝赋值(即重载=),则编译器会隐式地提供一个。这样的话,如果你再通过友元声明,进行全局的定义会造成调用二义性(即使允许,编译也会出错)。

2:对于所有楼主提到的操作符(=,[],(),->),只能声明为成员函数是为了避免不合法的书写通过编译(这是推测出……

这个有道理

#37


顶19楼

2楼3楼神逻辑!你们是学编程的吗??体育老师教的么..

#38


引用 21 楼 kingxuke 的回复:
@lZ
嗯,复合运算符确实合法,查了很久,还真没找到合理的原因,贴个测试代码,期待大神出现啊

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend const X& operator+=(const X& x1, const X& x2) { return x1; } // 只是测试,无意义
};

int main()
{
    X x;
    1 += x;// 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数

    return 0;
}


楼主和我,Good Luck!


帖子有点早了,但是看到之后收获很多。我觉得 kingxuke 解释的很好,这样看来为了避免1+=x或者1=x之类的语句,是应该把=
写作成员函数而不是友元函数,多谢!

#39


引用 21 楼 kingxuke 的回复:
@lZ
嗯,复合运算符确实合法,查了很久,还真没找到合理的原因,贴个测试代码,期待大神出现啊

#include <iostream>

class X 
{
public:
    X(){}
    X(int){} // int 类型可以被隐式转换成 X
    friend const X& operator+=(const X& x1, const X& x2) { return x1; } // 只是测试,无意义
};

int main()
{
    X x;
    1 += x;// 合法,使用友元重载函数,1 可以被隐式地转换为 X 类型 --友元函数的第一个参数

    return 0;
}


楼主和我,Good Luck!


不过我倒有另外一个问题看,1被隐式转换为X类型后,系统应该是创造了一个临时的X类对象吧,然后调用+=的时候,x1就是这个临时对象的引用吧?那么返回x1之后岂不是“返回了一个临时变量的引用”了吗?