操作符重载手册
上一篇 / 下一篇 2009-09-03 15:17:06 / 个人分类:C# && .NET
51Testing软件测试网I'D/LCf6Ss1s
51Testing软件测试网._b q^p T_
#Z `)TmO0
c3d\4Z;[Q g%s01.一元操作符可以是不带参数的成员函数[1]或带一个参数的非成员函数[1]。
["S1t']a7ge&q$Y02.二元操作符可以是带一个参数的成员函数[1]或带两个参数的非成员函数[1]。
m(RK'n \7f9bt03.operator=、operator[]、operator()、operator->只能定义为成员函数[1]。
#Mt&Q \.j)h2CvW04.operator->的返回值必须是一个指针或能使用->的对象。
+S$B2N#\,M7i+JYk05.重载 operator++ 和 operator-- 时带一个 int 参数表示后缀,不带参数表示前缀。51Testing软件测试网`Q+g{C
6.除 operator new 和 operator delete 外,重载的操作符参数中至少要有一个非内建数据类型。51Testing软件测试网~5x!wia V$U
7.x@y 搜索范围为:x 成员函数--> 全局函数/X所在名字空间中的函数/Y所在名字空间中的函数/X的友元函51Testing软件测试网l}~ {6a'tIS-kF_jQ
数/Y的友元函数。
WV8nhC+xt&r"aN08.重载的的操作符应尽量模拟操作符对内建类型的行为。51Testing软件测试网)TW e&AzQ`-t
1B*u,M5^G+?*O+A5C0
o9AYt6Q'W!s3_b0
&Ly$W#`j"t$KEa"l051Testing软件测试网#W4Us8FQ|)D
2A#\yI
?!h,y051Testing软件测试网V
o8S"F8\kp*j9B
1.只将会改变第一个参数的值的操作符(如: +=)定义为成员函数,而将返回一个新对象的操作符(如: +)定义为非成员函数(并使用 += 来实现)。51Testing软件测试网wY!oSJ$}'n8b0B2^
2.只有非成员函数才能在左参数上实施性别转换,如果需要进行转换则应将操作符定义为非成员函数。
v3i R_]0R|7S%eY0 3.对一元操作符, 为避免隐式转换最好将其重载为成员函数。
`)N@"q
j G.hw6d0 4.对二元操作符, 为能在左操作数上能进行和右操作数一样的隐式转换, 最好将其重载为非成员函数。51Testing软件测试网3}~@]'R\;^jL
5.为了遵照使用习惯,operator>>、operator<< 应定义为非成员函数。
!H_
B7c#M0 6.重载 operator[] 之类的操作符, 应尽量提供 const 版本和非 const 版本。
eQ$@/k.?s%BYG0 7.关于将操作符定义为成员或非成员可参考以下建议:
1} @ nB.L\F051Testing软件测试网[1QPO}m(W3ITJ&o
| ||||||||||||
|
6t Snvw2J'A$}s051Testing软件测试网dx,z]V/q8O
8.如果默认操作符已经可以施用于你的型别上, 则应尽量避免重载此操作符. 如 operator, 、operator&(取地址) 等等.
)y,R2GS"U0
TX$rKl0
T6mC2Y4r#]qR0
}%l
cKCj%l$X8D0 1.为什么要重载 operator new ?51Testing软件测试网UC{!nMz@B@/S
51Testing软件测试网$r,{1BT'nt4T&gF
[改变行为] 默认的分配器失败时会抛出异常, 或许你想改变这种行为.51Testing软件测试网9Y\L,k&|Zf3T-p
1gJ5?:M-V1dv#y&e%EIv*V0
4P
i#N f B2?B0 2. operator new 的行为51Testing软件测试网)SiBj1{.Q9W
e"P:~#gH051Testing软件测试网lr
Qi-XIr
new 操作符(new 表达式, new operator, new expression): 通常我们调用 X * pX = new X 时使用的就是这个操作符, 它由语言内建, 不能重载, 不能改变其行为. 它包括分配内存的 operator new 和调用构造函数的 placement new.
*W!qC1W$Q)}0 operator new :opeator new 是一个函数, void * operator new(size_t size) . 它分配指定大小的内存, 可以被重载, 可以添加额外的参数, 但第一个参数必须为 size_t. operator new 除了被 new operator 调用外也可以直接被调用: void * rawMem = operator new(sizeof(X)).
4K{O:u:x)R*e2C0 placement new : placement new 在一块指定的内存上使用构造函数, 包含头文件 <new> 之后也可以直接使用placement new: X * pX = new (rawMem) X.[2]51Testing软件测试网K`w o%q9Q f~0A
C%?C9^cb1|I0 与 new operator 类似, 对于 delete operator, 也存在 operator delete: void operator delete(void *), 析构方法 pX->~X().51Testing软件测试网1\`3SehrGw"s#V
51Testing软件测试网z;Vy:K#BfW
[operator new 的错误处理]
8`*g.c1Zo0 默认的 operator new 在内存分配失败时将会抛出 std::bad_alloc 异常;nothrow new[3]51Testing软件测试网-O$N e:\VU,R7K
(X * pX = new (nothrow) X) 在内存分配失败时将会返回 0 . 这种行为可以通过设置 new-handler 来改变. new-handler 是一个回调函数指针, typedef void(*new_handler)(void). 通过 set_new_handler(new_handler) 函数设置回调句柄后, 如果分配内存失败, operator new 将会不断的调用 new-handler 函数, 直到找到足够的内存为止. 为了避免死循环, new-handler 函数必须具备以下行为之一:
H4u6K;?"K0 (1).找到可用的内存.51Testing软件测试网7ThVv e!Omq*`
(2).安装其它的 new-handler 函数.
{-X~+V?+B0 (3).卸除 new-handler, 即 set_new_hanlder(0), 这样下此循环将恢复默认行为抛出异常或返回 0.
(D6L8} K"Oa0 (4).抛出异常.51Testing软件测试网'dB:Y E~*p
(5).保存错误日志, 退出程序.51Testing软件测试网(E^$B)T'o{_
^'uo;t:vJ0
/\8^p,nbayxZ?0 3.准备重载 operator new51Testing软件测试网n0O#g1wNK%Q%uU`E
51Testing软件测试网^]1]a*rb`1l
{
$X,IR.e7yf h9L1`0 if(size == 0)
!^u:[ X+X$A1ibp0 size = 1;
k mv$|&c$kn YP0
CuH"i}!DA0 while(1)51Testing软件测试网,RG#AFkr
{51Testing软件测试网2BB)Q WFp5BF+E
... // allocate memery51Testing软件测试网6E0R4E|U$U-[@e#Iy
if(allocate sucessfull)51Testing软件测试网'vexA)x:RNw
return ... // return the pointer.51Testing软件测试网'`p#GL}a C?
iE0ogi0R3A'Z{*v{0 new_handler curhandler = set_new_handler(0);
g7hZ"^/u"[y6_'X)^0 set_new_handler(curhandler); // get current new handler51Testing软件测试网7\SqF5|1A)aA^
51Testing软件测试网+{ ?R$f;vu.\*w(e
if(curhandler == 0)
/KohYpd3T7}:[0 (*curhandler)();
l8B,q ys0 else
{%n8mog9`f2P0 throw std::bad_alloc();51Testing软件测试网`$j }/I{LH2^
}51Testing软件测试网'tS|]#T
}51Testing软件测试网8P@-A~Xp\Z
51Testing软件测试网-`'K,N.pygY
4.重载 operator new
&b5D&~0~5JA0
ouf(B
M(X"F051Testing软件测试网K6j3zi(Z7O:wZ"s
0k"s6C|2INqW0[★ 用不同的参数重载 operator new]
Re:H{+FY"B$h0
V1g7mf+g0 通过使用不同的参数类型, 可以重载 operator new, 例如 :
{
uz Nx\dY0 ...51Testing软件测试网:W8FS L.HS9h
}
isZH c Bi0
G'JU!W(i4k0X * pX = new (1, 2, 3) X;
3H1wJh#~Y&iI0{
|q9C*j-u6yn ZG4]:hr0 ...51Testing软件测试网F#G0G5o9L
}51Testing软件测试网(} M:M`+Y
6vY9w#wI.\djN0X * pX = new (10) X;51Testing软件测试网fkAj!iC0@
Y * pY = new (10, 10) Y;
Q'_:U'n3U3D0Z * pZ = new (10, 10, 10) Z;51Testing软件测试网LsDS#qTas
9~5pc;_Wmk%[:L0...
ax}:[$xZ ZL0void * operator new(size_t size, ...)
)v~r+h:a:i%?b0...
51Testing软件测试网ZiP U3NF C a|
[★ 重载 class 专属的 operator new]
u3h*O4E(lX;Nw0
v_+A.z4nA0 为某个 class 重载 operator new 时必须定义为类的静态函数[4], 因为 operator new 会在类的对象被构建出来之前调用. 即是说调用 operator new 的时候还不存在 this 指针, 因此重载的 operator new 必须为静态的. 当然在类中重载 operator new 也可以添加额外的参数, 并可以使用默认值.另外, 和普通函数一样, operator new 也是可以继承的.
_]i]$~Dv3Gwu0...
V _8j,L1av8a6D0static void * operator new(size_t size); // ... (1)
;V[A)y n n.W:[0static void * operator new(size_t size, int); // ... (2)
%E)E?M GG0};51Testing软件测试网h-M8yW,u @S
1J9`s0wYGf0class Y : public X{
^^4}3I)S(j9Na0...51Testing软件测试网i2D2An'PPs
};51Testing软件测试网.m.[~ x/Ee{
T&onA?$l0class Z : public X{51Testing软件测试网0DL1C7n^
...51Testing软件测试网(l D5PB0r@p
static void * operator new(size_t size); // ... (3)
7f3|eEQ/s0};
'E1nMbZ,^&fD J051Testing软件测试网)~V8ZCe'@8n
X * pX1 = new X; // call (1)51Testing软件测试网\"[(Jn9Aa;@"k\
X * pX2 = ::new X; // call default operator new51Testing软件测试网*a}#_'aL-}?
X * pX3 = new (0) X; // call (2)
dWK`#{n(R051Testing软件测试网e,v'cJ o3sD g
Y * pY1 = new Y; // call (1)51Testing软件测试网p`5M(U7]&z!@6H
7xk9s[VY0Z * pZ1 = new Z; // call (3)51Testing软件测试网!Llg*L._F^d
Z * pZ2 = ::new Z; // call default operator new
;EY:d-w;?EKRG"\0Z * pZ3 = X::new Z; // error, no way to call (1)51Testing软件测试网V*?sA:?7R V}1o
Z * pZ4 = new (0) Z; // error, no way to call (2)51Testing软件测试网n1OG'eO
H\0MU&df051Testing软件测试网-i~,S
W"l-mO
5.重载 operator delete
1Sh g0D+W3t
`$H051Testing软件测试网:mf1F.LKr
51Testing软件测试网*RUUyb*xF$v6L
如果在类中使用 operator delete, 也必须将其声明为静态函数. 因为调用 operator delete 时对象已经被析构掉了. operator delete 的重载可以有两种形式:
W-Z`}os$B `0(1) void operator delete(void * mem)51Testing软件测试网j~/Qg.m(r^.VO
(2) void operator delete(void * mem, size_t size)
wh3rLt\@0 并且这两种形式的 operator delete 可以同时存在, 当调用 delete px 时, 如果 (1) 式存在的话将调用 (1) 式. 只有在 (1) 式不存在时才会调用 (2) 式. 对第 (2) 种形式的 operator delete, 如果用基类指针删除派生类对象, 而基类的析构函数没有虚拟的时候, size 的值可能是错误的.
/G$mhD9l6l051Testing软件测试网0Z
S9KI7I*DnD
qU`']"}i0展开全部
|(Y|3~V9]8l$Tj1Jd051Testing软件测试网[2|m4dS#i#F
+const Carrot operator+(const Carrot& lhs, const Carrot& rhs)
Carrot result = lhs;51Testing软件测试网Sp,~x2R5Z.kKD
return result += rhs;
&T!|Ba9EQ0}51Testing软件测试网#u2Y ]2kCFI3}I4T6H
\z4gNu9oZc,Y0【注】1. 如果可能, 应考虑使用 operator+= 来实现 operator+ .51Testing软件测试网!M*\(c6[6Bp
2. operator+ 不能返回引用, 应返回值类型.51Testing软件测试网9Chvpme5H gw
3. 为了阻止形如 (a + b) = c 的调用, 应将返回值声明为 const .
· const Carrot operator-(const Carrot& lhs, const Carrot& rhs)
0fg4C'[t#zx0+const Carrot operator*(const Carrot& lhs, const Carrot& rhs)
h{{Zfn0 ...
W d3Cp3C0Xi U!Y A0}
*?4`,h:Q2r JP0
· const Carrot operator/(const Carrot& lhs, const Carrot& rhs)51Testing软件测试网(C xb@7I E+B*Ch&Y"a
· const Carrot operator%(const Carrot& lhs, const Carrot& rhs)51Testing软件测试网-~(Mn%lC
· const Carrot operator^(const Carrot& lhs, const Carrot& rhs)
]qp0h4d]2lUW/f f n0+const Carrot operator&(const Carrot& lhs, const Carrot& rhs)
,} V,PPsl0 ...
a&yA_hxY'yd0}51Testing软件测试网a'e_9i1|\?qQ
· const Carrot operator|(const Carrot& lhs, const Carrot& rhs)
z&B3X&t t;V0+const Carrot Carrot::operator-() const
Carrot result = (*this);
5p6m@D(K9Nm$o0V,H&S0 ... // chang the value to negative
6MMt$^"Ge }0 return result;
)k{"`XC%oIP{M0}
5E~O1AG2YYv0
【注】1. 一元操作符, 取负.
Q&P4Eex5hcx1C5k4v#A0
@O l"o?K0· const Carrot Carrot::operator~() const
nT-ii&w/MW'G*]0· bool Carrot::operator!() const
9o#TE3J%C|:D0· bool operator>(const Carrot& lhs, const Carrot& rhs)51Testing软件测试网bNa7h*z;G
· bool operator<(const Carrot& lhs, const Carrot& rhs)51Testing软件测试网9UPIW.P
+Carrot& Carrot::operator=(const Carrot& rhs)
if(this == &rhs)
U$dnA,i}(|,pn0 return *this; // may be (*this) == rhs if needs.
uK+Co6~6r/@o~?w051Testing软件测试网v.D1mT C*AT3i }K;n
Barley::operator=(rhs); // if Carrot derived from Barley51Testing软件测试网s];P%]l
(Aa^EC8Cg0 ... // assignments every memeber of Carrot.
&~)t0t|P051Testing软件测试网 sK%O"|$Q])eR
return *this;51Testing软件测试网a4E4y"~v8c}
}51Testing软件测试网 `OD'q3O R5m/W
"wJ`,?/['T0【注】1. 为了实现形如 x=y=z=0 的串联赋值操作, perator= 必须传回 *this 的非常量引用.
4y3{"EP7M DY6f0 2. 在赋值时应注意检查是否为自赋值 ( a = a ).
5x"js:Y!]&vN&\+Dk1z0+Carrot& Carrot::operator+=(const Carrot& rhs)
...
+K5JnoS1it!y.V4p0 return *this;
HAp'x]u'H0}51Testing软件测试网N%Wl4K;AIE4GT
【注】1. C++ 允许 (x += 1) = 0 形式的赋值操作, operator+= 必须传回 *this 的非常量引用.
· Carrot& Carrot::operator-=(const Carrot& rhs)
:TB%H8\8q4N0· Carrot& Carrot::operator*=(const Carrot& rhs)
N}H-MVi,i0· Carrot& Carrot::operator/=(const Carrot& rhs)51Testing软件测试网/ALU7ygk&A
· Carrot& Carrot::operator%=(const Carrot& rhs)51Testing软件测试网]1ICrq
· Carrot& Carrot::operator^=(const Carrot& rhs)51Testing软件测试网"SJ'{,N(]3Jp4}
· Carrot& Carrot::operator&=(const Carrot& rhs)
P|4LD\5c }0· Carrot& Carrot::operator|=(const Carrot& rhs)51Testing软件测试网$F0a\1D+KHC%S
+istream& operator>>(istream& _IStr, Carrot& rhs)
W&GP0Jb%Re0 ...
:X/cyv3K"qZ0 return _IStr;51Testing软件测试网9_O {kr*w:\
}
9^?%j.G(`h-urF0
8Z*|:GY@yP0【注】1. 为了遵照使用习惯(cin>>x 而不是 x>>cin), 对流操作的 operator>> 应为非成员函数.51Testing软件测试网|i,Se.]
`}poF7I1F;i:]0+ostream& operator<<(ostream& _OStr, const Carrot& rhs)
...
7m;F`0iM$H Z N O0 return _OStr;
)hK][l"K6P3}-ge0}
5CDW-NP4r L0
8Y6}T+r |-{0b0+const Carrot operator>>(const Carrot& lhs, int rhs)
Carrot result = lhs;
#tU:Sl)KX6jAb6m0 ...
Lq"E%pF`.p{0 return result;
&\_#q:}+t~y4~%]0}
g.dqLN'H9L`B GA0
【注】1. 移位操作的重载方式.51Testing软件测试网&\m N^&d-_-P0F;P:L9dp
?sZ*O:D1U~'q8Avf*oo0· const Carrot operator<<(const Carrot& lhs, int rhs)51Testing软件测试网b!hcGF!T`
+Carrot& Carrot::operator>>=(int rhs)
@%V9`7hO/K+O0 ...51Testing软件测试网X;I,F&@']Ss7Ec
return *this;51Testing软件测试网,X'xt9@8FvoO5c
}51Testing软件测试网~6{4?@8\E+D
'u.l{Qd O0【注】1. 移位操作.
I aO.u#Tq`\0· Carrot& Carrot::operator<<=(int rhs)51Testing软件测试网1ox A4n!a,kg+R#M#p
+bool perator==(const Carrot& lhs, const Carrot& rhs)