友元函数与友元类
《C++ primer 》这本书上的源码,类Sales_data实现
#include<iostream>
#include<string>
using namespace std;
class Sales_data
{
public:
Sales_data();//声明一个无参的构造函数
Sales_data(string b, int u, double p) :bookno(b), units_sold(u), price(p){}//声明一个有参数的默认构造函数,用参数的初始化表对数据成员初始化
friend istream& operator >> (istream &, Sales_data &);//运算符>>重载为友元函数
friend ostream& operator << (ostream &, Sales_data &);//运算符<<重载为友元函数
friend Sales_data operator + (Sales_data & lhs, Sales_data & rhs);//声明友元的运算符重载 + 函数
Sales_data& operator = (const Sales_data &);//重载赋值运算符
friend bool operator == (Sales_data &, Sales_data &);//声明有元的重载双目运算符==函数
Sales_data &operator += (const Sales_data &);//声明一个返回sales_item类型的重载运算符+=函数,形参采用常量引用
double avg_price();
string isbn() const;//声明isbn函数,并返回书编号
Sales_data& combine(const Sales_data &);//一个combine成员函数,用于将一个Sales_data对象加到另一个对象上
//声明Sales_data类的非成员接口函数
friend istream &read(istream&, Sales_data&);//声明一个read函数,将数据从istream读入到Sales_data对象中,函数返回类型为istream &
friend ostream &print(ostream&, const Sales_data&);//声明一个print函数,函数返回类型为ostream &
friend Sales_data add(const Sales_data &, const Sales_data &);//一个add的函数,执行两个Sales_data对象的加法
private:
string bookno;//书号
double units_sold;//销售出的册数
double price;//单本售价
double revenue;//总销售额
double average;
};
Sales_data::Sales_data()//定义无参数的构造函数
{
bookno = "null";
units_sold = 0;
price = 0.0;
}
istream& operator >>(istream &input, Sales_data &s)//对重载运算符>>进行定义
{
input >> s.bookno >> s.units_sold >> s.price;
if (input)
{
s.revenue = s.units_sold * s.price;
}
return input;
}
ostream& operator << (ostream &output, Sales_data &s)//对重载运算符<<进行定义
{
//output << s.bookno << " "<< s.units_sold << " " << s.revenue << " " << s.price << endl;
output << s.bookno << " " << s.units_sold << " " << s.revenue << " " << s.avg_price() << endl;
return output;
}
//将两个sales_item对象相加时,程序应该检测其两个对象的isbn书号是否相同
Sales_data operator + (Sales_data & lhs, Sales_data & rhs)//定义重载运算符+函数,lhs和rhs是sales_item的对象
{
Sales_data ret;
ret.bookno = lhs.bookno;
ret.units_sold = lhs.units_sold + rhs.units_sold;
ret.revenue = lhs.revenue + rhs.revenue;
ret.avg_price();
return ret;
}
bool operator == (Sales_data &lhs, Sales_data &rhs)
{
return lhs.units_sold == rhs.units_sold && lhs.price == rhs.price && lhs.isbn() == rhs.isbn();
}
Sales_data& Sales_data:: operator = (const Sales_data &lhs)//重载赋值运算符=
{
bookno = lhs.bookno;
units_sold = lhs.units_sold;
price = lhs.price;
return *this;
}
Sales_data& Sales_data ::operator += (const Sales_data &rhs)//
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;//将this对象作为左值返回,*this相当于一个sales_item对象
}
//定义一个avg_price()常量成员函数
double Sales_data::avg_price()
{
average = revenue / units_sold;
return average;
}
//定义一个isbn()常量成员函数
string Sales_data::isbn() const
{
return bookno;
}
//一个combine成员函数,用于将一个Sales_data对象加到另一个对象上
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
//友元函数read()的具体实现,将数据从istream读入到Sales_data对象中
istream &read(istream &input, Sales_data &rhs)
{
input >> rhs.bookno >> rhs.units_sold >> rhs.price;
rhs.revenue = rhs.units_sold * rhs.price;
return input;
}
//友元函数add()的具体实现,执行两个Sales_data对象的加法
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
sum.avg_price();
return sum;
}
从上面Sales_data中的read、print和add函数,前面加一个关键字friend,此结构即称为友元函数。
- 友元函数不属于类的成员函数,他是定义在类外的普通函数,只是在类中声明该函数可以直接访问类中的private或者protected成员,但是它的声明可以放在类的私有部分,也可放在共有部分类。
- 友元函数的定义在类体外实现,不需要加限定。
- 一个类中的成员函数可以是另外一个类的友元函数,而且一个函数可以是多个类的友元函数。
- 友元函数可以访问类中的私有成员和其他数据,但是访问不可直接使用数据成员,需要通过对对象进行引用。
- 友元函数在调用上同一般函数一样,不必通过对对象进行引用。
- 每个类负责控制自己的友元类或友元函数
以下两种方法是对以上几点的验证:
#include<iostream>
#include"Sales_data.h"
using namespace std;
int main()
{
Sales_data total, s;
if (read(cin, total))
{
Sales_data trans;
//友元函数在调用上同一般函数一样,不必通过对对象进行引用
while (read(cin, trans))
{
if (total.isbn() == trans.isbn())
{
cout << add(total, trans) << endl;
}
else
{
cout << "两本书编号不一样" << endl;
cout << total << endl;
cout << trans << endl;
}
}
}
else
{
cout << "输入为空:" << endl;
}
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
class Father{
friend class Son; //一种方法是把Son类作为它的友元类
public:
Father(int s);
//friend void Son::run(Father &w); //另一种方法是把Son类的成员函数做了友元函数。
private:
int age;
};
Father::Father(int s)
{
age = s;
}
class Son{
public:
Son(char *pn);
void run(Father &w); //成员函数,做成Father类中友元函数实现
private:
char name[20];
};
Son::Son(char *pn)
{
strcpy_s(name, pn);
}
void Son::run(Father &w) //Son类成员函数的实现Father
{
cout << "name: " << name << " age: " << w.age << endl;
}
int main()
{
Father w(30);
Son c("SZZ");
c.run(w);
return 0;
}
上述代码运行结果
: