目录 Table of Contents
5 操作符重载与临时对象
operator overloading 操作符重载-1, 成员函数 this
inline complex&
__doapl(complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
inline complex&
complex::operator += (const complex& r)
{
return __doapl(this, r);
}
inline complex&
complex::operator += (this, const complex& r)
{
return __doapl(this, r);
}
所有的成员函数一定带着一个隐藏的参数 this 指针, 我们写代码不必写也不能写这个参数, 因为一写就会报错
但是你在函数里面可以用它 return __doapl(this, r);
return by reference 语法分析
传递者无需知道接受者是以 reference 形式接收
你可能会对这个写法感到疑惑
inline complex&
__doapl(complex* ths, const complex& r)
{
// ...
return *ths;
}
这个是上一节说的加的那个过程
返回的时候是返回的指针指的一个东西, 然后函数上面写的是返回的一个引用, 你返回的是一个 value, 接收方接收的是引用, 这个是可以的, 因为传递者无需知道接受者是以引用的形式接收
class body 之外的各种定义 (definitions)
现在我们讲一下头文件布局的类-定义部分
inline double
imag(const complex& x)
{
return x.imag();
}
inline double
real(const complex& x)
{
return x.real();
}
取得某一个复数的虚部和实部
operator overloading (操作符重载-2, 非成员函数) (无 this)
为了对付 client 的三种可能用法, 这里对应开发三个函数
inline complex
operator + (const complex& x, const complex& y)
{
return complex(real(x) + real(y), imag(x) + imag(y));
}
inline complex
operator + (const complex& x, double y)
{
return complex(real(x) + y, imag(x));
}
inline complex
operator + (double x, const complex& y)
{
return complex(x + real(y), imag(y));
}
下面是使用这些函数, 顺序一一对应
{
complex c1(2, 1);
complex c2;
c2 = c1 + c2;
c2 = c1 + 5;
c2 = 7 + c1;
}
因为数学上告诉我们, 一个复数可以和一个实数加在一起
写了好几个函数的话, 编译器就会去找对应的函数
和前面的不同之处在于, 这个没有指针, 前面的有指针
temp onject (临时对象) typename();
还是上面的三个函数
他们返回的不是引用, 而是值 value, 因为他们返回的是 local object
先前的例子是把右边加到左边身上 +=, 结果放到左边去; 这个是相加并没有说放到哪里, 所以势必要在这个函数里面创建一块地方出来, 放这个结果
那这种东西会随着函数的结束而被释放, 所以就只能传值出去, 因为一传引用, 函数释放了, 变量也释放了, 外面想要用的话就没得用了
刚刚是说应该在函数里面创建一个东西来保存结果的, 但是代码里面好像并没有 ?
这里有一个特殊语法, return complex(real(x) + real(y), imag(x) + imag(y));
, 一个类的名称, 也就是 typename, 直接在后面加上一个小括号 (), 这个就是创建临时对象
临时对象就是临时要的, 不想给它名称, 到了代码下一行就死了
这种特殊语法一般人可能很少用, 但是在标准库里面经常用
operator overloading (操作符重载), 非成员函数
inline bool
operator == (const complex& x, const complex& y)
{
return real(x) == real(y) && imag(x) == imag(y);
}
inline bool
operator == (const complex& x, double y)
{
return real(x) == y && imag(x) == 0;
}
inline bool
operator == (double x, const complex& y)
{
return x == real(y) && imag(y) == 0;
}
下面是用法举例
{
complex c1(2, 1);
complex c2;
cout << (c1 == c2);
cout << (c1 == 2);
cout << (0 == c2);
}
// 共轭复数
inline complex
conj(const complex& x)
{
return complex(real(x), -imag(x));
}
#include <iostream.h>
ostream&
operator << (ostream& os, const complex& x)
{
return os << '(' << real(x) << ',' << imag(x) << ')';
}
<<
运算符重载, 现在只能用全局的写法, 非成员函数
如果把这个返回类型改成 void 会怎么样 ?
一般的输出是没有问题的, 因为你是直接扔在了屏幕上, 但是像下面这种连续输出的就不行了
cout << c1 << conj(c1);
先输出 c1, 得到的结果还要继续能够接受 conj(c1)
总结
设计一个 class 要注意什么事情 ?
构造函数的 initialization list 一定要会用
函数该不该加 const
参数的传递尽量考虑传递引用
返回的时候考虑返回引用
数据尽可能放到 private 里面
函数大部分放在 public