C++教程-C++中的友元函数
C++中的友元函数
正如我们已经知道的,在面向对象的编程语言中,类的成员可以访问类的数据和函数,但外部函数无法访问类的数据。然而,有时候外部函数需要访问类的私有成员,这时候就需要用到友元函数。
什么是友元函数?
友元函数是在类的范围之外定义的函数,但它具有访问类的所有私有和保护成员的权限。
友元函数出现在类的定义中,但友元函数本身是成员函数。
友元函数的特点:
- 友元函数不在其被声明为友元的类的作用域内。
- 不能使用对象调用友元函数,因为它不在该类的作用域内。
- 可以像普通函数一样调用友元函数,无需使用对象。
- 不能直接访问成员名称,而必须使用对象名和成员名的点成员运算符。
- 友元函数可以在类的私有或公有部分声明。
为什么我们需要在C++中使用友元函数?
- 在C++中,友元函数用于直接访问类的私有数据,而不使用该类的对象。
- 友元函数还用于执行运算符重载。就像我们已经了解到的函数重载一样,运算符也可以通过运算符重载进行重载。
友元函数的特点:
- 友元函数使用friend关键字声明。
- 它不是类的成员,但是它是类的友元。
- 由于它不是类的成员,因此可以像普通函数一样定义。
- 友元函数不能直接访问类的数据成员,而是将一个对象作为参数传递。
- 它类似于普通函数。
- 如果我们想在函数中共享多个类的数据,则可以使用友元函数。
友元函数声明的语法如下:
class class_name
{
friend data_type function_name(argument/s); // 友元函数的语法
};
在上述声明中,友元函数前面带有关键字friend。该函数可以像普通的C++函数一样在程序的任何地方定义。函数定义不使用关键字friend或作用域解析运算符。
让我们通过一个例子来理解友元函数。
#include <iostream>
using namespace std;
class Distance
{
private:
int meters;
public:
// 构造函数
Distance()
{
meters = 0;
}
// display_data() 方法的定义
void display_data()
{
std::cout << "Meters value : " << meters<<std::endl;
}
// 友元函数的原型。
friend void addvalue(Distance &d);
};
// 友元函数的定义
void addvalue(Distance &d) // 参数包含引用
{
d.meters = d.meters+10; // 将meters的值增加10
}
// main() 方法
int main()
{
Distance d1; // 创建Distance类的对象
d1.display_data(); // meters = 0
addvalue(d1); // 调用友元函数
d1.display_data(); // meters = 10
return 0;
}
在上面的代码中,Distance是一个类,它包含名为'meters'的私有字段。Distance()是构造函数,它将'meters'的值初始化为0。display_data()是一个方法,用于显示'meters'的值。addvalue()是Distance类的友元函数,用于修改'meters'的值。在main()方法中,d1是Distance类的对象。
输出:
友元函数在处理两个不同类的对象时也非常有用。
让我们通过一个例子来理解。
// 使用友元函数将两个不同类的成员相加
#include <iostream>
using namespace std;
// 类的前向声明
class ClassB;
// 类的声明
class ClassA {
public:
// 构造函数 ClassA() 将 num1 初始化为 12
ClassA()
{
num1 = 12;
}
private:
int num1; // 整数变量的声明
// 友元函数声明
friend int multiply(ClassA, ClassB);
};
class ClassB {
public:
// 构造函数 ClassB() 将 num2 初始化为 2
ClassB()
{
num2 = 2;
}
private:
int num2; // 整数变量的声明
// 友元函数声明
friend int multiply(ClassA, ClassB);
};
// 访问两个类的成员
int multiply(ClassA object1, ClassB object2)
{
return (object1.num1 * object2.num2);
}
int main() {
ClassA object1; // ClassA对象的声明
ClassB object2; // ClassB对象的声明
cout << "两个数相乘的结果为: " << multiply(object1, object2);
return 0;
}
在上述代码中,我们定义了两个名为ClassA和ClassB的类。由于ClassA被声明为ClassB的友元,因此ClassA可以访问ClassB的所有数据成员。在ClassB中,我们定义了一个名为add()的函数,它返回num1和num2的和。由于ClassB被声明为ClassA的友元,因此我们可以在ClassB中创建ClassA的对象。
正如我们在上述代码中观察到的,ClassA中的友元函数也在没有先前声明ClassB的情况下使用了ClassB。因此,在这种情况下,我们需要提供ClassB的前向声明。
输出:
友元类在C++中
也可以通过friend关键字创建。
class Class1;
class Class2
{
// Class1是Class2的友元类
friend class Class1;
.. .....
};
class Class1
{
....
};
在上述声明中,Class1被声明为Class2的友元类。Class1可以访问Class2的所有成员。
让我们通过一个例子来理解友元类。
// C++程序,演示友元类的工作
#include <iostream>
using namespace std;
// 前向声明
class ClassB;
class ClassA {
private:
int num1;
// 声明友元类
friend class ClassB;
public:
// 构造函数,将numA初始化为10
ClassA()
{
num1 = 10;
}
};
class ClassB {
private:
int num2;
public:
// 构造函数,将numB初始化为1
ClassB()
{
num2 = 1;
}
// 成员函数,将num1和num2相加
int add() {
ClassA objectA;
return objectA.num1 + num2;
}
};
int main() {
ClassB objectB;
cout << "Sum: " << objectB.add();
return 0;
}
在上面的代码中,我们创建了两个名为ClassA和ClassB的类。由于ClassA被声明为ClassB的友元类,所以ClassA可以访问ClassB的所有数据成员。在ClassB中,我们定义了一个名为add()的函数,它返回num1和num2的和。由于ClassB被声明为ClassA的友元类,所以我们可以在ClassB中创建ClassA的对象。
输出: