1、重载操作符没必要一定是成员函数,还可以是友元函数。
2、重载操作符函数为成员函数主要是你需要操作类内部的成员,
必须是成员函数或友元函数才行。
3、至于由深浅拷贝的原因要使其成为成员函数,这个不知道。
4、如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。
如果运算符被重载为类的成员函数,那么一元运算符没有参数,二元运算符只有一个右侧参数,因为对象自己成了左侧参数。
从语法上讲,运算符既可以定义为全局函数,也可以定义为成员函数。文献[Murray , p44-p47]对此问题作了较多的阐述,并总结了表8-4-1的规则。
运算符
规则
所有的一元运算符
建议重载为成员函数
= () [] ->
只能重载为成员函数
+= -= /= *= &= |= ~= %= >>= <<=
建议重载为成员函数
所有其它运算符
建议重载为全局函数
第四点来自 http://shake863.iteye.com/blog/213590
由上面的代码可以知道,如果将 =,[],(),-> 进行友元全局重载,那么就会出现 1=x; 1[x]; 1->x; 1(x); 这样的合法语句(起码编译器认为这些是合法的)--参考代码中的 if(1<x) 合法的片段,但显然这些是需要避免的,当然这些不是我们程序员的责任,应该有语言的设计者来实现,所以,就……。
2、重载操作符函数为成员函数主要是你需要操作类内部的成员,
必须是成员函数或友元函数才行。
3、至于由深浅拷贝的原因要使其成为成员函数,这个不知道。
4、如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,有两个参数的运算符叫做二元运算符。
如果运算符被重载为类的成员函数,那么一元运算符没有参数,二元运算符只有一个右侧参数,因为对象自己成了左侧参数。
从语法上讲,运算符既可以定义为全局函数,也可以定义为成员函数。文献[Murray , p44-p47]对此问题作了较多的阐述,并总结了表8-4-1的规则。
运算符
规则
所有的一元运算符
建议重载为成员函数
= () [] ->
只能重载为成员函数
+= -= /= *= &= |= ~= %= >>= <<=
建议重载为成员函数
所有其它运算符
建议重载为全局函数
第四点来自 http://shake863.iteye.com/blog/213590
简单地说,C++标准规定要这样使用,但为什么要这样规定,请看下面:
1:对于赋值操作符(=)--比较特别,因为任何类如果不提供显示的拷贝赋值(即重载=),则编译器会隐式地提供一个。这样的话,如果你再通过友元声明,进行全局的定义会造成调用二义性(即使允许,编译也会出错)。
2:对于所有楼主提到的操作符(=,[],(),->),只能声明为成员函数是为了避免不合法的书写通过编译(这是推测出的原因,更深层的可能要研究 C++ 的设计了)。这涉及到 C++ 中类型的隐式转换。下面通过代码例子说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#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) 合法的片段,但显然这些是需要避免的,当然这些不是我们程序员的责任,应该有语言的设计者来实现,所以,就……。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#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;
}
|