C++中的友元函数

时间:2020-02-23 14:29:57  来源:igfitidea点击:

C++中的"友元函数"是一类函数,可以作为类的公共函数/外部访问类的私有成员和受保护成员。

您可能想知道;这有可能吗?好吧,现代的C++说是的!

让我们看看如何在C++中使用这些函数。

C++中的友元函数

如果函数定义以friend关键字为前缀,则将函数称为友元函数。

我们不能在类外使用friend前缀,因此只能在成员函数声明中使用。

例如,如果我们想在声明中使用friend关键字,可以这样使用:

#include <iostream>

using namespace std;

class MyClass {
  private:
      int a, b;
  public:
      MyClass(int a, int b) {
          //Constructor
          this->a = a;
          this->b = b;
      }
      void set_a(int val);
      void set_b(int val);
      int get_a() {
          return a;
      }
      int get_b() {
          return b;
      }
      //Declare a friend function of this class
      friend void my_fun(MyClass& my_obj, int val, char option);
};

void my_fun(MyClass& my_obj, int val, char option) {
  //Friend function that sets the private variables
  //based on the option
  if (option == 'a') {
      //Set a
      my_obj.a = val;
  }
  else {
      //Set b
      my_obj.b = val;
  }
}

int main() {
  MyClass my_obj(1, 2);
  cout << "my_obj.a = " << my_obj.get_a() << " and my_obj.b = " << my_obj.get_b() << endl;

  //Friend functions can be accessed from outside the class!
  my_fun(my_obj, 20, 'a');
  my_fun(my_obj, 40, 'b');
  cout << "my_obj.a = " << my_obj.get_a() << " and my_obj.b = " << my_obj.get_b() << endl;
  return 0;
}

其中my_fun()是MyClass的友元函数,因此它也可以访问私有成员!

注意,我们也可以从类外部访问友元函数。

上面的friend函数直接设置私有成员" a"或者" b"的值!

输出

my_obj.a = 1 and my_obj.b = 2
my_obj.a = 20 and my_obj.b = 40

友元函数可以在同一类中,甚至可以在另一类中。
但是它必须是成员函数。

让我们一一看一下这两种情况。

C++中同一类中的Friend 函数

上面的例子向我们展示了我们可以在同一个类中使用一个友元函数。

class MyClass {
  private:
      int a, b;
  public:
      MyClass(int a, int b) {
          //Constructor
          this->a = a;
          this->b = b;
      }
      void set_a(int val);
      void set_b(int val);
      int get_a() {
          return a;
      }
      int get_b() {
          return b;
      }
      //Declare a friend function of this class
      //within the same class itself!
      friend void my_fun(MyClass& my_obj, int val, char option);
};

我们将继续处理下一种情况;当一个友元函数在另一个类中时!

实际上,这是另一个主题,称为"友元班",但是它们彼此直接相关。

C++中的友元类–另一个类中的友元函数

具有另一个类别A的友元功能的任何类别B称为A的友元类别。

与友元功能相似,友元类B中的任何成员函数都可以访问A的私有成员和受保护成员。

让我们通过一个例子更清楚地了解这一点。

我将使用前面的示例,但将添加另一个类" Student",并将其作为" MyClass"的友元类。

#include <iostream>
#include <string>

using namespace std;

class Student;

class MyClass {
  private:
      int a, b;
  public:
      MyClass(int a, int b) {
          //Constructor
          this->a = a;
          this->b = b;
      }
      void set_a(int val);
      void set_b(int val);
      int get_a() {
          return a;
      }
      int get_b() {
          return b;
      }
      //Declare a friend function of this class
      friend void my_fun(MyClass& my_obj, int val, char option);
      //Make Student a friend Class of MyClass
      friend Student;
};

现在,让我们编写"学生"类:

class Student {
  private:
      string name;   
      int marks;
  public:
      Student(string s_name, int s_marks) {
          //Constructor
          name = s_name;
          marks = s_marks;
      }
      int get_marks() {
          return marks;
      }
      string get_name() {
          return name;
      }
      void set_marks(Student& stud, int s_marks) {
          stud.marks = s_marks;
      }
      void set_name(Student& stud, string s_name) {
          stud.name = s_name;
      }
      void change_a(MyClass& my_obj, int val) {
          //You need to pass the object by reference.
          //Otherwise, it will not reflect the changes on
          //the original object
          my_obj.a = val;
      }
      void change_b(MyClass& my_obj, int val) {
          //You need to pass the object by reference.
          //Otherwise, it will not reflect the changes on
          //the original object
          my_obj.b = val;
      }
};

如您所见,我正在使用change_a()change_b()直接更改MyClass对象的属性!

现在,让我们运行下面的完整代码段。

#include <iostream>
#include <string>

using namespace std;

class Student;

class MyClass {
  private:
      int a, b;
  public:
      MyClass(int a, int b) {
          //Constructor
          this->a = a;
          this->b = b;
      }
      void set_a(int val);
      void set_b(int val);
      int get_a() {
          return a;
      }
      int get_b() {
          return b;
      }
      //Declare a friend function of this class
      friend void my_fun(MyClass& my_obj, int val, char option);
      //Make Student a friend Class of MyClass
      friend Student;
};

class Student {
  private:
      string name;   
      int marks;
  public:
      Student(string s_name, int s_marks) {
          //Constructor
          name = s_name;
          marks = s_marks;
      }
      int get_marks() {
          return marks;
      }
      string get_name() {
          return name;
      }
      void set_marks(Student& stud, int s_marks) {
          stud.marks = s_marks;
      }
      void set_name(Student& stud, string s_name) {
          stud.name = s_name;
      }
      void change_a(MyClass& my_obj, int val) {
          //You need to pass the object by reference.
          //Otherwise, it will not reflect the changes on
          //the original object
          my_obj.a = val;
      }
      void change_b(MyClass& my_obj, int val) {
          //You need to pass the object by reference.
          //Otherwise, it will not reflect the changes on
          //the original object
          my_obj.b = val;
      }
};

void my_fun(MyClass& my_obj, int val, char option) {
  //Friend function that sets the private variables
  //based on the option
  if (option == 'a') {
      //Set a
      my_obj.a = val;
  }
  else {
      //Set b
      my_obj.b = val;
  }
}

int main() {
  MyClass my_obj(1, 2);
  cout << "my_obj.a = " << my_obj.get_a() << " and my_obj.b = " << my_obj.get_b() << endl;

  //Friend functions can be accessed from outside the class!
  my_fun(my_obj, 20, 'a');
  my_fun(my_obj, 40, 'b');
  cout << "my_obj.a = " << my_obj.get_a() << " and my_obj.b = " << my_obj.get_b() << endl;

  //Class Student objects
  Student stud("Amit", 34);
  cout << "stud.name = " << stud.get_name() << " and stud.marks = " << stud.get_marks() << endl;

  //Change my_obj.a and my_obj.b using the friend class
  stud.change_a(my_obj, 100);
  stud.change_b(my_obj, 200);
  
  cout << "After using the Friend Class methods,\n";
  cout << "my_obj.a = " << my_obj.get_a() << " and my_obj.b = " << my_obj.get_b() << endl;
  return 0;
}

输出

my_obj.a = 1 and my_obj.b = 2
my_obj.a = 20 and my_obj.b = 40
stud.name = Amit and stud.marks = 34
After using the Friend Class methods,
my_obj.a = 100 and my_obj.b = 200

实际上,"友元"类方法所做的更改确实反映在" my_obj"中。