友元函数
形式
friend 类型名 友元函数名(形参表);
然后在类体外对友元函数进行定义,定义的格式和普通函数相同,但可以通过对象作为参数直接访问对象的私有成员
说明如下
1)必须在类的说明中说明友元函数,说明时以关键字friend开头,后跟友元函数的函数原型,友元函数的说明可以出现在类的任何地方,包括在private和public部分;
2)注意友元函数不是类的成员函数,所以友元函数的实现和普通函数一样,在实现时不用"::"指示属于哪个类,只有成员函数才使用"::"作用域符号;
3)友元函数不能直接访问类的成员,只能访问对象成员,
4)友元函数可以访问对象的私有成员,但普通函数不行;
5)调用友元函数时,在实际参数中需要指出要访问的对象,
6)类与类之间的友元关系不能继承。
7)一个类的成员函数也可以作为另一个类的友元,但必须先定义这个类。
友元函数使用的一个例子,摘自 C++ primer 中文版 第6版:
#include <iostream>
#include <string>
using namespace std;
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m = 0);
void AddMin(int m);
void AddHr(int h);
void Reset(int h = 0, int m = 0);
Time operator+(const Time &t)const;
Time operator-(const Time &t)const;
Time operator*(double n)const;
friend Time operator*(double mult, const Time &t);/* friend function */
/*std::ostream& */
friend ostream & operator<<(ostream & os, const Time &t);/* friend function */
void Show()const;
};
Time::Time()
{
hours = minutes = 0;
}
Time::Time(int h, int m)
:hours(h),minutes(m)
{
}
void Time::AddMin(int m)
{
minutes += m;
hours += minutes/60;
minutes %= 60;
}
void Time::AddHr(int h)
{
hours += h;
}
void Time::Reset(int h, int m)
{
hours = h;
minutes = m;
}
Time Time::operator+(const Time &t)const
{
Time sum;
sum.minutes = t.minutes + this->minutes;
sum.hours = t.hours + this->hours + (sum.minutes / 60);
sum.minutes %= 60;
return sum;/* 不能返回局部变量的引用 */
}
Time Time::operator-(const Time &t)const
{
Time des;
int tm1, tm2;
tm1 = t.minutes + t.hours * 60;
tm2 = this->minutes + this->hours * 60;
des.minutes = (tm2 - tm1) % 60;
des.hours = (tm2 - tm1) / 60;
return des;
}
Time Time::operator*(double mult)const
{
Time res;
long ttmin = (this->hours * 60 + minutes) * mult;
res.hours = ttmin / 60;
res.minutes = ttmin % 60;
return res;
}
void Time::Show()const
{
cout<<hours<<" hours "<<minutes<<" minutes "<<endl;
}
/* friend union */
/* 由于成员函数运算符*的表达式方式是 Time * double ,但是有时候我们会写成 double * Time 的格式
这时候编译器不会调用 operator*,因为左侧的操作数不是对象。
解决这种问题的方式是使用友元:
1.声明友元函数
2.创建友元函数
*/
inline Time operator*(double mult, const Time &t)
{
return t * mult;
}
/* 有了友元函数,就可以运算表达式 double * Time */
/* 常用友元:重载 <<运算符 */
std::ostream & operator<<(std::ostream &os, const Time &t)
{
os<<t.hours<<" hours "<<t.minutes<<" minutes ";
return os;/* 调用后返回cout对象,后续的cout才能正常工作 ,详见 C++primer 6 中文版394页 */
}
int main()
{
Time weeding(4, 35);
Time waxing(2, 47);
Time total;
Time des;
Time adjusted;
cout<<"weeding time = ";
weeding.Show();
cout<<endl;
cout<<"waxing time = ";
waxing.Show();
cout<<endl;
cout<<"total work time =";
total = waxing + weeding;
total.Show();
cout<<endl;
cout<<"weeding time - waxiang time = ";
des = weeding - waxing;
des.Show();
cout<<endl;
cout<<"adjustice 1.5 times work time = ";
adjusted = total * 1.5;
adjusted.Show();
cout<<endl;
Time aida(3, 35);
Time tosca(2, 48);
Time temp;
cout<<"Aida and Tosca:\n";
cout<<aida<<" ; "<<tosca<<endl;
temp = aida + tosca;
cout<<"Aida + Tosca = "<<temp<<endl;
temp = aida * 1.17;
cout<<"Aida * 1.7 = "<<temp<<endl;
cout<<"10 * Tosca = "<< 10 * tosca<<endl;
return 0;
}
运算结果:
li@li:~/C++$ ./friend
weeding time = 4 hours 35 minutes
waxing time = 2 hours 47 minutes
total work time =7 hours 22 minutes
weeding time - waxiang time = 1 hours 48 minutes
adjustice 1.5 times work time = 11 hours 3 minutes
Aida and Tosca:
3 hours 35 minutes ; 2 hours 48 minutes
Aida + Tosca = 6 hours 23 minutes
Aida * 1.7 = 4 hours 11 minutes
10 * Tosca = 28 hours 0 minutes
关于重载运算符<<:上边程序的例子中使用友元重载<<
C++ 能够使用流提取运算符 >> 和流插入运算符 << 来输入和输出内置的数据类型。您可以重载流提取运算符和流插入运算符来操作对象等用户自定义的数据类型。
在这里,有一点很重要,我们需要把运算符重载函数声明为类的友元函数,这样我们就能不用创建对象而直接调用函数。
下面的实例演示了如何重载提取运算符 >> 和插入运算符 <<:
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 到无穷
int inches; // 0 到 12
public:
// 所需的构造函数
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
friend ostream &operator<<( ostream &output,
const Distance &D )
{
output << "F : " << D.feet << " I : " << D.inches;
return output;
}
friend istream &operator>>( istream &input, Distance &D )
{
input >> D.feet >> D.inches;
return input;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11), D3;
cout << "Enter the value of object : " << endl;
cin >> D3;
cout << "First Distance : " << D1 << endl;
cout << "Second Distance :" << D2 << endl;
cout << "Third Distance :" << D3 << endl;
return 0;
}