一个类的私有数据不能被另一个类的非成员函数访问。有时我们希望两个类共享一些函数和数据成员。在这种情况下,我们可以将函数声明为这些类的**友元**,从而允许它访问类的私有和受保护数据成员。本教程将通过简单的例子涵盖 C++ 中友元函数的含义、为什么需要友元函数以及友元函数有哪些特殊特性等重要概念。
**友元函数**是一个外部提供的函数,它可以访问类成员的受保护和私有数据。这意味着一个函数,它不是一个类的成员,但它有权访问该类的受保护和私有成员,被称为**友元函数**。
函数模板、成员函数、类或类模板,或者函数,都可以被视为友元。如果一个类是友元,那么该类的每个成员也都是友元。友元函数是典型的外部函数,被赋予了特殊的访问权限,它们不是类成员。
有时,允许某个类访问另一个类的私有成员是有益的。例如,LinkedList 类可能被允许访问 Node 的私有成员。
例如
#include<iostream>
using namespace std;
class A {
int x;
public:
A() {
x = 50;
}
friend class B; //friend class
};
class B {
public: void display(A & t) {
cout << endl << "value of x=" << t.x;
}
};
main() {
A _a;
B _b;
_b.display(_a);
return 0;
}
输出
value of x=50
在这种情况下,类 B 已在类 A 中被声明为友元。因此,B 是类 A 的友元。类 A 的私有成员可供类 B 访问。
友元函数: 友元函数可以被赋予特定的权限来访问私有和受保护成员,就像友元类一样。
友元函数可以是:
语法
class <class_name>
{
friend <return_type> <function_name>(arg list);
};
语法解释
示例
#include<iostream>
using namespace std;
class Largest {
int x, y, z;
public:
void set_data();
friend void find_max(Largest);
};
void Largest::set_data() {
cout << "Please Enter the First Number:";
cin >> x;
cout << "Please Enter the Second Number:";
cin >> y;
}
void find_max(Largest t) {
if (t.x > t.y)
t.z = t.x;
else
t.z = t.y;
cout << "Maximum Number is\t" << t.x;
}
main() {
Largest l;
l.set_data();
find_max(l);
return 0;
}
输出
Please Enter the First Number: 50 Please Enter the Second Number:100 Maximum Number is : 100
在某些特殊情况下,我们需要友元函数,这些情况下需要直接访问类的私有数据,而无需使用该类的对象。考虑以下类:Director 和 Doctor。对于这些类的每个对象,我们可能希望使用 gross_salary 函数。该函数不一定属于这些类中的一个。
它们也用于运算符重载,因为它们更直观。友元函数方法可以用于重载常用的二元算术运算符。
友元类可以使用它被声明为友元的另一个类的数据、成员和函数。当我们需要授予特定类访问不同类的私有和受保护成员的权限时,就会使用它们。
所有被声明为另一个类的友元类的成员函数都转换为该友元类的友元函数。为了连接这些类,需要友元函数。
友元类的语法
class S; //forward declaration
class P{
// Other Declarations
friend class S;
};
class S{
// Declarations
};
在上面的示例中,类 S 被认为是类 P 的友元。因此,类 S 可以访问类 P 成员的私有数据。这并不意味着类 P 的成员可以访问类 S 成员的私有数据。在实体正式定义之前,编译器通过前向声明被告知其存在。
为了让编译器知道类 S 存在,我们使用前向声明声明了它,从而允许我们在类 P 中使用类 S 对象。
需要注意的是,类的友元关系不是继承的或相互的,除非我们明确这样设置。这意味着,因为类 S 是类 P 的友元,所以类 S 也将是类 P 的子类的友元。
#include <iostream>
using namespace std;
// forward declaration
class ClassY;
class ClassX {
int digit1;
// friend class declaration
friend class ClassY;
public:
// constructor to initialize num1 to 10
ClassX() : digit1(10) {}
};
class ClassY {
int digit2;
public:
// constructor to initialize num2 to 5
ClassY() : digit2(5) {}
// member function to multiply num1
// from ClassX with num2 from ClassY
int multiply() {
ClassX m;
return m.digit1 * digit2;
}
};
int main() {
ClassY n;
cout << "Multiplication: " << n.multiply();
return 0;
}
输出
Multiplication :50
在上面的程序中,声明了两个类 X 和 Y。ClassX 将 ClassY 作为友元类。因此,ClassY 可以访问 ClassX 的成员函数。我们在 ClassY 中开发了一个名为 multiply() 的函数,它返回数字 1 和 2 相乘的结果。
我们可以在 ClassY 内部创建 ClassX 的对象,因为 ClassY 是一个友元类。提前声明 ClassY 是可以实现的。