1.为什么需要友元函数
#include "stdafx.h" #include <iostream> #include <string> using namespace std; class Wealth { private: long gold; long silver; long copper; public: Wealth(long gold, long silver, long copper) { this->gold = gold; this->silver = silver; this->copper = copper; } //重载+运算符,将两份财产相加 Wealth operator+ (Wealth& wealth) const { long copperTotal = this->copper + wealth.copper; long silverTotal = this->silver + wealth.silver; long goldTotal = this->gold + wealth.gold; return Wealth(goldTotal+silverTotal/100, (silverTotal+copperTotal/100)%100, copperTotal%100); } //重载+运算符,将财产加上一个铜币数 Wealth operator+(long copper) { long copperTotal = this->copper + copper; return Wealth(this->gold + (this->copper + copperTotal / 100) / 100, (this->copper + copperTotal / 100) % 100, copperTotal % 100); } string toString() { return "you have: " + to_string(this->gold) + " golds, " + to_string(this->silver) + " silvers and " + to_string(this->copper) + " coppers"; } }; int main(void) { Wealth w1(10, 10, 10); Wealth w2(90, 90, 90); Wealth w = w1 + w2; cout << w.toString() << endl; w = w + 1; //w = 1 + w; //没有与这些操作数匹配的 + 运算符 cout << w.toString() << endl; cin.get(); return 0; }
上面的代码中, w = w + 1是可以通过编译的,但是 w = 1 + w 不行,这样一个类提供出去显然不行。
w = w + 1可以,是因为operator+是类的成员函数,所以w = w + 1实际上是 w = w.operator+(1),所以w = 1 + w 编译不过也可以理解了,因为 1 这个int里面没有operator+这个函数
解决这样的问题,就需要友元函数出马,代码如下,将此函数加入Wealth类
//友元函数,重载+运算符,将财产加上一个铜币数 //虽然operator+是在Wealth类里定义的,但却不是Wealth的成员函数,也不能使用wealth.operator+来调用 //编译能够将1+wealth与operator+(1,wealth)匹配起来 friend Wealth operator+(long copper, Wealth &wealth) { long copperTotal = wealth.copper + copper; return Wealth(wealth.gold + (wealth.copper + copperTotal / 100) / 100, (wealth.copper + copperTotal / 100) % 100, copperTotal % 100); }
2.还有哪种情况必须要使用友元函数
如果想要使用 cout << wealth 来打到wealth.display()的效果该怎么办呢,cout << 之所以能支持许多不同基本类型的输出,是因为ostream类里面对<<进行了许多重载以支持这些类型。但是显然我们不能修改ostream类,而只能是让Wealth类知道如何使用cout。
显然这也需要使用友元函数,为什么?因为我们需要的效果是cout << wealth,如果使用一个成员函数来重载 << ,Wealth对象将是第一个操作数,这意味着必须像下面这样使用<<:
wealth << cout
这会让人困惑,但是友元函数就不同了,很OK了,因为它可以这样
void operator<< (ostream& os, const Wealth& wealth)
{
os << 略
}
具体见下面的示例代码