朋友功能 - 实用吗?

时间:2012-01-13 12:03:10

标签: c++ oop

  

可能重复:
  When should you use 'friend' in C++?

There is a detailed explanation here,但我想知道朋友功能的实际用途。

我如何决定何时应该使用朋友功能而不是成员功能?

3 个答案:

答案 0 :(得分:2)

在大多数情况下,friend声明是代码气味,因为它破坏了封装

开发人员经常使用friend来快速解决问题。然而,良好的起始设计或一些重构(通常更多的重构)排除了它的必要性。

编辑:

即使在@ Darhuuk的例子中,也不需要朋友声明。您可以为要打印的特定字段设置getter。

答案 1 :(得分:2)

当函数需要成为非成员时,您会使用朋友,但也需要访问类成员。

需要非成员函数的常见示例包括:

  • 需要非会员功能的API;例如,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;
}