class complex
{
public :
complex ( double r = 0 , double i = 0 ) : re ( r) , im ( i) { }
complex ( ) : re ( 0 ) , im ( 0 ) { }
complex& operator += ( const complex& ) ;
double real ( ) const { return re; }
double image ( ) const { return im; }
private :
double re, im;
friend complex& __doapl ( complex* , const complex& ) ;
} ;
const
在函数只使用数据而不修改数据时,在函数参数列表后加上const
加const表示该函数保证不修改传入的数据。 如果不加const,使用者对const对象调用该函数时,编译器会报错。因为不加const表示该函数可能会修改数据,而const对象无法被修改。
complex c1 ( 2 , 1 ) ;
cout<< c1. real ( ) ;
cout<< c1. image ( ) ;
const complex c2 ( 2 , 1 ) ;
cout<< c2. real ( ) ;
cout<< c2. image ( ) ;
参数传递
pass by value
把value全部传过去,value有多大,传的包就有多大。传的动作就是把value压到函数的栈中去。 double类型的数据是4个字节就传4个字节,如果是100个字节也就传递100个字节 尽量不要传值,传引用
pass by reference
引用在底部就是指针,传引用就相当于传指针一样快 传加const的引用,表示虽然传的是引用,但是不能修改数据
返回值传递
尽量返回引用 不能返回引用的情况:一个函数的操作结果
如果放在现有位置,则可以返回引用 如果要新创建一个变量存储结果则返回值。
相同class的各个objects互为friends
class complex
{
public :
complex ( double r = 0 , double i = 0 ) : re ( r) , im ( i) { }
int func ( const complex& param)
{ return param. re + param. im; }
private :
double re, im;
} ;
{
complex c1 ( 2 , 1 ) ;
complex c2;
c2. func ( c1) ;
}
运算符重载
成员函数运算符重载
任何成员函数都有一个隐藏的this指针,指针指向调用者。
inline complex&
__doapl ( complex* ths, const complex& r)
{
. . .
return * ths;
}
inline complex&
complex:: operator += ( const complex& r)
{
return __doapl ( this , r) ;
}
传引用的好处:传递者无需知道接收者是用什么形式来接收的
inline complex&
__doapl ( complex* ths, const complex& r)
{
. . .
return * this ;
}
inline complex&
complex:: operator += ( const complex& r)
{
return __doapl ( this , r) ;
}
对+=的重载为什么返回引用,返回void可以吗
返回void,对于没有连续赋值的情况完全适用 返回引用,可以满足连续赋值的情况 当使用者可能会连续使用该重载运算符时,要做更多的设计
{
complex c1 ( 2 , 1 ) ;
complex c2 ( 5 ) ;
c2 += c1;
c3 += c2 += c1;
非成员函数运算符重载
+的重载
不能返回引用,只能返回值,为什么
因为加的结果是一个新的值,需要新的空间来存储 返回引用绑定的是一个局部变量,一旦函数结束会被释放,会留下巨大的隐患 不是成员函数
typename():表示创建临时对象,typename是待创建对象的类型
inline complex
operator + ( const complex& x, const complex& y)
{
return complex ( real ( x) + real ( y) , imag ( x) + umag ( y) ) ;
}
对输出运算符<<,只能重载为非成员函数
cout是一个ostream对象,可以先把cout理解为屏幕,输出就是将<<的右边数据写入到cout中 cout会连续输出,所以重载<<要返回对ostream的引用
# include <iostream.h>
ostream&
operator << ( ostream& os, const complex& x)
{
return os<< '(' << real ( x) << ','
<< imag ( x) << ')' ;
}
标准库中的complex类的设计过程
写防卫式的常数定义 写class的头 思考复数应该具有的数据类型,将它们放在private中 思考类内要有哪些函数 4.1 构造函数,接受哪些参数,是否有默认值,传值还是传引用,列表初始化,函数体(如分配内存,打开一个窗口,打开一个文件等) 4.2运算符重载,成员函数还是非成员函数,参数传递,返回类型 4.3读取数据的函数,函数是否加const 在类外写类中声明函数的实现 5.1 写操作符重载接口,先写函数全名,成员函数默认运算符左边是this所指的对象,考虑传入参数是否传引用,传入参数是否为const,返回类型是否为引用,是否加inline 5.2 写接口的实现,是否需要调用辅助函数 重载输出运算符 6.1 输入输出运算符不是成员函数,因为cout在运算符左侧,类对象在运算符右侧 6.2 ostream传引用,被输出的对象不会被修改,加const 6.3 cout会被改变,函数不是const函数 6.4 使用ostream要引入头文件,可以在使用前引入所需的头文件,不一定全部在整个文件的头(最好是在文件头) 6.5 为了可以连续使用该运算符<<,返回类型设为引用而不是void 6.6 写输出复数的格式
类的设计总结
数据一定是private 参数尽可能的传引用,根据实际要求判断是否加const 返回值尽可能的传引用 类中的函数应该加const的都要加 构造函数尽量使用列表初始化