答案 0 :(得分:2)
在大多数情况下,friend
声明是代码气味,因为它破坏了封装。
开发人员经常使用friend
来快速解决问题。然而,良好的起始设计或一些重构(通常更多的重构)排除了它的必要性。
编辑:
即使在@ Darhuuk的例子中,也不需要朋友声明。您可以为要打印的特定字段设置getter。
答案 1 :(得分:2)
当函数需要成为非成员时,您会使用朋友,但也需要访问类成员。
需要非成员函数的常见示例包括:
boost::intrusive_ptr
要求您将intrusive_add_ref()
和intrusive_release()
实现为非成员函数。operator<<(ostream&, my_type const &)
。int
构建,那么5 + my_type
将在您定义非成员operator+(my_type const&, my_type const&);
时起作用,但如果您定义成员my_type::operator+(my_type const &) const;
则不行。< / LI>
这些是否需要成为朋友取决于他们是否可以使用班级的公共界面完成工作;例如,您可以添加print(ostream&)
可以使用的公开operator<<
成员,以及operator+=
可以使用的公开operator+
成员。
以operator+
:
operator+=
的示例
my_type & my_type::operator+=(my_type const & rhs)
{
// do addition here
return *this;
}
// The first operand is passed by value, giving a modifiable copy
my_type operator+(my_type lhs, my_type const & rhs)
{
return lhs += rhs;
}
答案 2 :(得分:0)
最简单的用例可能是重载自定义类的流输出运算符。
例如,请查看以下代码(从here无耻地复制)。在这种情况下,使用friend
允许非类方法访问类的私有字段,从而防止需要编写几个get
方法(否则您甚至可能不想创建)。
#include <iostream>
#include <cstring>
using namespace std;
class MyClass {
// now private
char name[80];
int areacode;
int prefix;
int num;
public:
MyClass(char *n, int a, int p, int nm)
{
strcpy(name, n);
areacode = a;
prefix = p;
num = nm;
}
friend ostream &operator<<(ostream &stream, MyClass o);
};
ostream &operator<<(ostream &stream, MyClass o)
{
stream << o.name << " ";
stream << "(" << o.areacode << ") ";
stream << o.prefix << "-" << o.num << "\n";
return stream;
}
int main() {
MyClass a("T", 1, 5, 1);
MyClass b("A", 3, 5, 5);
MyClass c("T", 2, 5, 9);
cout << a << b << c;
return 0;
}