【译】友元函数和友元类

友元函数

原则上,类的private和protected成员不能在其声明的类外进行访问。但是,这一规则对友元不起作用。

友元是通过关键字friend声明的函数或类。

如果声明一个外部函数为一个类的友元,这样就允许此函数操作这个类的private和protected成员。通过在类的内部声明这个外部函数,并在其前面加上friend关键字: 

// friend functions
#include <iostream>
using namespace std;

class CRectangle {
    int width, height;
  public:
    void set_values (int, int);
    int area () {return (width * height);}
    friend CRectangle duplicate (CRectangle);
};

void CRectangle::set_values (int a, int b) {
  width = a;
  height = b;
}

CRectangle duplicate (CRectangle rectparam)
{
  CRectangle rectres;
  rectres.width = rectparam.width*2;
  rectres.height = rectparam.height*2;
  return (rectres);
}

int main () {
  CRectangle rect, rectb;
  rect.set_values (2,3);
  rectb = duplicate (rect);
  cout << rectb.area();
  return 0;
}

输出:24

函数duplicate是类CRectangle的一个友元。在这个函数内部我们就可以操作CRectangle不同对象的private成员width和height。无论是在duplicate声明中,还是在之后main()中的使用。我们都没有认为duplicate是类CRectangle的一个成员。它不是!它只是可以操作类的private和protected成员,而不是其成员。

友元函数可以作用于,例如,操作两个不同的类。通常来说,友元函数的运用已经超出了面向对象的编程方法,因此最好通过同一类的成员来操作此类。就像之前的例子,若将duplicate()整合到类CRectangle中,整个例子就会更加精简。

友元类

就像我们可以定义一个友元函数,我们也可以定义类的友元类。假设第一个类可以操作第二个类的protected和private成员。 

// friend class
#include <iostream>
using namespace std;

class CSquare;

class CRectangle {
    int width, height;
  public:
    int area ()
      {return (width * height);}
    void convert (CSquare a);
};

class CSquare {
  private:
    int side;
  public:
    void set_side (int a)
      {side=a;}
    friend class CRectangle;
};

void CRectangle::convert (CSquare a) {
  width = a.side;
  height = a.side;
}
  
int main () {
  CSquare sqr;
  CRectangle rect;
  sqr.set_side(4);
  rect.convert(sqr);
  cout << rect.area();
  return 0;
}

输出:16

在这个例子中,我们将CRectangle声明为CSquare的一个友元,因此CRectangle成员函数就可以操作CSquare的protected和private成员,具体就是描述正方形边长的CSquare::side。

你也可以在这段程序的开头看到一些新东西:类CSquare的空声明。这是需要的,因为在类CRectangle的声明中我们涉及到类CSquare(作为convert()的参数)。类CSquare的定义在后面,如果我们不在之前包括其空声明,CSquare在CRectangle定义内部就是不可见的。

友元不是相互的,如果我们不显示指定。在我们的例子中,CRectangle是类CSquare的一个友元,但是CRectangle并不认为CSquare是其友元。因此CRectangle可以操作CSquare的protected和private成员,但反之不然。当然,如果需要,我们可以将CSquare声明为CRectangle的一个友元。

原文:http://www.cplusplus.com/doc/tutorial/inheritance/

posted @ 2011-05-24 10:40  iThinking  阅读(321)  评论(0编辑  收藏  举报