被指定为某类的友元的函数称为该类的友元函数。
被指定为某类的友元的称为授予友元关系的那个类的友元类。
在需要允许某些特定的非成员函数访问一个类的私有成员(及受保护成员),而同时仍阻止一般的访问的情况下,友元是有用的。
使用友元的优点:可以灵活地实现需要访问若干类的私有或受保护成员才能完成的任务,通过使用友元函数重载,可以更自然地使用C++语言的I/O库。输入输出操作符的重载需要用友元来实现。
友元的缺点:一个类将对其非公有成员的访问权授予其他的函数或类,会破坏类的封装性,降低类的可维护性。
#include"stdafx.h"
#include<iostream>
#include<string>
class Sales_item {
public:
//将add函数指定为Sales_item类的友元
<span style="color:#ff0000;"> friend Sales_item add(const Sales_item&,const Sales_item&);
friend std::istream& read(std::istream&,Sales_item&);</span>
double avg_price() <span style="color:#ff0000;">const</span>;
bool same_isbn(<span style="color:#ff0000;">const</span> Sales_item &rhs)<span style="color:#ff0000;">const</span> { return isbn==rhs.isbn;}
//构造函数
Sales_item(<span style="color:#ff0000;">const</span> std::string& book=""):isbn(book),units_sold(0),revenue(0.0) { }
Sales_item(std::istream& is)
{
is>>isbn>>units_sold>>revenue;
}
private:
std::string isbn;
unsigned units_sold;
double revenue;
};
<span style="color:#ff0000;">inline</span> double Sales_item::avg_price() const
{
if(units_sold)
return revenue/units_sold;
else
return 0;
}
Sales_item add(const Sales_item& obj1,const Sales_item& obj2)
{
if(!obj1.same_isbn(obj2))
return obj1;
Sales_item temp;
temp.isbn=obj1.isbn;
temp.units_sold=obj1.units_sold+obj2.units_sold;
temp.revenue=obj1.revenue+obj2.revenue;
return temp;
}
std::istream& read(std::istream& is,Sales_item& obj)
{
double price;
is>>obj.isbn>>obj.units_sold>>price;
if(is)
obj.revenue=obj.units_sold*price;
else
obj=Sales_item();
return is;
}
int main()
{
Sales_item a(std::cin);
}
其他几点说明:
1、const关键词能用尽量用,多多益善。
2、将成员函数定义为内联函数的方式。
类内声明:double avg_price() const;
类外定义:
inline double Sales_item::avg_price() const
{
if(units_sold)
return revenue/units_sold;
else
return 0;
}
3、构造函数中的初始化,按照变量定义的顺序来初始化。
Sales_item(const std::string& book=""):isbn(book),units_sold(0),revenue(0.0) { }