友元函数
友元函数:类的友元函数是非成员函数但是其访问权限和友元函数一样。
先谈谈函数重载,函数重载或者函数多态旨在能够使用同名的函数来完成相同的基本操作。
运算符重载将重载的概念拓展到运算符上,允许C++运算符有多重含义。
C++允许将运算符重载扩展到用户定义的类型。
在C++中可以定义一个表示数组的类,并重载+运算符。这种简单的加法表示隐藏了内部机理,并强调了实质。这也是OOP的另一个目标。
在.h文件中
Time operator+(const Time & t) const
{
}
在use中,total = coding.operator+(fixing);
total = coding + fixing;
重载运算符有他的限制:
重载的运算符不必是成员函数但是必须至少有一操作数是用户自定义的类型。
重载后的operator至少有一个操作数是用户定义的类型。
使用运算符时不能违反运算符本身的语法规则
不能创建新的operator。
部分运算符不能重载
部分运算符必须通过成员函数进行重载
公有类方法是访问私有数据的唯一方法,以至于不合适特定的问题,友元函数赋予该函数与类成员函数相同的访问权限。
example
A = B * 2.75; //左侧操作数是调用对象。
A = 2.75 * B; //cmpiler不能使用成员函数来替换该表达式
解决方法:非成员函数,非成员函数不是由对象调用的,他所使用的所有值都是显示参数
非成员函数不能访问私有数据但是友元函数可以。
创建友元函数:
将其原型放在类声明中,并在原型上加速关键字friend
friend Time operator * (double m , const Time & t);
该函数在类声明中声明但是他不是类的成员函数,不能用成员运算符来调用。
该函数不是成员函数但是他和成员函数的访问权限相同
编写该函数的函数定义是不要::不要friend key words
Time operator * (double m, const Time & t)
因为类声明决定哪一个函数是友元函数因此类声明控制着那些函数可以访问类的私有数据类方法和友元函数只是表示类接口的两种不同形式。
如果要为类重载运算符并将非类的项作为其第一个操作数则可以使用友元函数来反转操作数的顺序。
对<<的重载
cout是一个ostream对象,他是智能的能够识别C++基本类型。
Time trip; cout << trip;
要使cout 能够识别Time对象,一种方法是讲一个新的函数运算符定义添加到ostream声明中,但修改istream是个危险的主意。通过Time类对象声明让Time类对象知道如何使用cout
要使Time类对象知道如何使用cout必须使用友元函数,如果使用一个Time类对象的成员函数来重载<<time类对象将是第一个操作数 trip<<cout。
void operator<<(ostream &os, const Time & t)
{
}
新的Time类声明使用operator<<函数成为Time类的一个友元函数,因为operator<<()直接访问Time对象的私有数据。所以他必须是Time类的友元函数。但是由于他不直接访问ostream对象的私有成员所以他不必是ostream类友元函数,
重载运算符:作为成员函数还是非成员函数
很多运算符可以选择采样成员函数还是非成员函数来实现运算符重载。一般非成员函数是友元函数。这样他才能直接访问类的私有数据。
加法操作符需要两个操作数,对于成员函数版本,一个操作数通过this指针隐式的传递另一个操作数作为函数参数显示传递
对于友元函数来说两个操作数都是作为参数来传递。
非成员函数版本重载运算符函数需要的形参数目与运算符所属于的操作数数目相同。
而成员函数版本所需要的形参数目少一个。因为其中一个操作数是被隐式传递的调用对象。
对于某些运算符来说成员函数是唯一的合法选择。