现在的位置: 首页 > 综合 > 正文

C++ 友元函数(Friend)

2013年03月29日 ⁄ 综合 ⁄ 共 1408字 ⁄ 字号 评论关闭

在类的外部,任何实例访问类的 private 或 protected 成员都是被禁止的,这是出于安全性的考虑。但是很多时候,出于实用性的考虑,的确需要从外部访问类的 private 或 protected 的成员,这可以在 C++ 中通过关键字 friend 来实现。

友元(friend)机制允许一个类将对其非公有成员(private 和 protected 成员)的访问授予指定的函数或类。友元函数必须要在类的内部进行声明,友元不是授予友元关系的那个类成员,出于编码风格的考虑,通常将友元声明橙组地放置在类定义的开头或结尾处


一、全局函数作为友元

// Friend_Global.cpp
#include <iostream>

using namespace std;

class Base {
  int value;   // 私有成员 
protected:
  string str;  // 保护成员 
public:
  Base(const string newStr, const int ii) :
    str(newStr), value(ii) {}
  
  friend void view(Base&);  // 声明friend的全局函数 
};

void view(Base& b) {  // 接受的是基类对象 
  cout << "string = " << b.str << endl
       << "value  = " << b.value << endl;
  return ;
}

int main() {
  Base b("Base", 49);
  view(b);
  /*
  //  任何实例,在类的外部试图访问
  //  类的private或protected成员都是被禁止的 
  cout << "string = " << b.str << endl
       << "value  = " << b.value << endl;
  */
  return 0;
}

运行结果:

值得注意的是,使用friend关键字修饰的全局函数void view(Base& b)并非是Base类的成员函数,它仅仅是全局函数


二、其它类的成员函数成为友元

// Friend_Class.cpp
#include <iostream>

using namespace std;

class Y;  // 因为在类X中的view函数中出现了Y,因此必须事先声明类Y 

class X {
public:
  /*
    参数类型声明为指针,因为类Y的定义在下方,
    在Y的定义之前,编译器或许并不知道应该为Y的对象
    分配多大的内存空间,而如果是Y*指针的话,编译器
    作了一次不完全的类型匹配,编译器知道如何传递一个
    地址,这一地址有具体的大小,而不管被传递的是什么
    对象,即使它还没有完全知道这种对象类型的大小
    
    虽然事实上传递对象也是可以的,但是在这种情况下,
    传递一个对象的地址更为安全! 
  */
  void view(const Y*);
};

class Y {
  int value;   // 私有成员 
protected:
  string str;  // 保护成员 
public:
  Y(const string newStr, const int ii) :
    str(newStr), value(ii) {}
  
  friend void X::view(const Y*);  // 声明X类的view方法为友元,允许在函数内部访问Y类的私有成员和保护成员 
};

void X::view(const Y* y) {
  cout << "string = " << y->str << endl
       << "value  = " << y->value << endl;
  return ;
}

int main() {
  Y y("Base", 49);
  X x;
  x.view(&y);
  return 0;
}

运行结果:


抱歉!评论已关闭.