C++之友元函数与友元类

友元函数与友元类

《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;
}

上述代码运行结果

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值