一、概述
在 C++ 中,友元函数(Friend Function)是一个能够访问类中私有成员和保护成员的函数,即使它不是该类的成员。友元函数在某些情况下非常有用,例如当两个类需要相互访问私有成员时,或者需要某个函数访问类的私有数据,但又不想将该函数作为类的成员。
友元函数的特点
- 访问权限:友元函数可以访问类的所有成员,包括私有成员和保护成员。
- 非成员函数:友元函数不是类的成员函数,但它可以在类的内部访问私有和保护成员。
- 定义和声明:友元函数需要在类内部使用
friend
关键字声明,但实际定义可以在类外部进行。 - 作用范围:友元函数不受类的访问控制限制,但其作用范围依然在其定义所在的命名空间内。
二、友元函数的声明和定义
1.声明友元函数:
- 在类的内部声明友元函数,并使用
friend
关键字。 - 友元函数声明的格式如下:
-
class MyClass { private: int data; public: // 声明友元函数 friend void printData(const MyClass& obj); };
2.定义友元函数:
- 友元函数的定义和普通函数一样,可以在类的外部进行。
- 友元函数定义的格式如下:
void printData(const MyClass& obj) {
std::cout << "Data: " << obj.data << std::endl;
}
3.使用友元函数:
- 友元函数可以像普通函数一样使用,并且可以访问类的私有成员和保护成员。
MyClass obj(42);
printData(obj); // 调用友元函数,输出:Data: 42
三、友元函数的使用场景
友元函数
- 访问权限:友元函数可以访问类的所有成员,包括私有成员和保护成员。这是友元函数最显著的特点和优势。
- 声明方式:友元函数必须在类的定义中使用
friend
关键字声明。
#include <iostream>
class MyClass {
private:
int data;
public:
MyClass(int value) : data(value) {}
// 声明友元函数
friend void printData(const MyClass& obj);
};
// 定义友元函数
void printData(const MyClass& obj) {
std::cout << "Data: " << obj.data << std::endl;
}
int main() {
MyClass obj(42);
printData(obj); // 友元函数可以访问私有成员
return 0;
}
成员函数
- 访问权限:成员函数只能访问所属类的成员(包括私有成员、保护成员和公有成员)。成员函数根据其访问修饰符(public、protected、private)可以访问不同的成员。
- 声明方式:成员函数在类的内部声明,并可以在类的内部或外部定义。
#include <iostream>
class MyClass {
private:
int data;
public:
MyClass(int value) : data(value) {}
// 成员函数
void printData() const {
std::cout << "Data: " << data << std::endl;
}
};
int main() {
MyClass obj(42);
obj.printData(); // 成员函数可以访问私有成员
return 0;
}
普通非成员函数
- 访问权限:普通的非成员函数不能直接访问类的私有成员和保护成员,除非通过公有接口或使用友元机制。
- 声明方式:普通非成员函数在类外部声明和定义,与类没有直接的关联。
#include <iostream>
class MyClass {
private:
int data;
public:
MyClass(int value) : data(value) {}
// 公有函数
int getData() const {
return data;
}
};
// 普通非成员函数
void printData(const MyClass& obj) {
std::cout << "Data: " << obj.getData() << std::endl;
}
int main() {
MyClass obj(42);
printData(obj); // 普通非成员函数通过公有接口访问私有成员
return 0;
}
四、在不同类中使用友元函数
步骤
- 前向声明类:如果两个类相互需要作为对方的友元,可能需要先进行前向声明。
- 在目标类中声明友元函数:在其中一个类中声明另一个类的成员函数作为友元函数。
- 定义友元函数:在友元函数所在的类外部定义该友元函数。
#include <iostream>
// 前向声明 ClassB
class ClassB;
class ClassA {
private:
int valueA;
public:
ClassA(int val) : valueA(val) {}
// 声明 ClassB 的成员函数为友元函数
friend void showValueFromB(const ClassB& b);
};
class ClassB {
private:
int valueB;
public:
ClassB(int val) : valueB(val) {}
// 声明一个成员函数
void showValue(const ClassA& a) const;
// 声明 showValue 为友元函数
friend void showValueFromB(const ClassB& b);
};
// 定义 ClassB 的成员函数
void ClassB::showValue(const ClassA& a) const {
std::cout << "Value from ClassA: " << a.valueA << std::endl;
}
// 定义友元函数
void showValueFromB(const ClassB& b) {
std::cout << "Value from ClassB: " << b.valueB << std::endl;
}
int main() {
ClassA a(10);
ClassB b(20);
b.showValue(a); // 输出 ClassA 的值
showValueFromB(b); // 输出 ClassB 的值
return 0;
}
类A的成员函数作为类B的友元
- 前向声明类:为了让
ClassA
和ClassB
互相访问,有时需要进行前向声明。
class ClassB;
- 在目标类中声明友元函数:在
ClassA
中声明ClassB
的成员函数showValueFromB
为友元函数。
friend void showValueFromB(const ClassB& b);
- 在另一个类中声明和定义成员函数:在
ClassB
中声明和定义showValue
成员函数,用于访问ClassA
的私有成员。
void ClassB::showValue(const ClassA& a) const {
std::cout << "Value from ClassA: " << a.valueA << std::endl;
}
- 定义友元函数:在类外部定义友元函数
showValueFromB
,它可以访问ClassB
的私有成员。
void showValueFromB(const ClassB& b) {
std::cout << "Value from ClassB: " << b.valueB << std::endl;
}
- 使用友元函数和成员函数:在
main
函数中,通过ClassB
的成员函数showValue
访问ClassA
的私有成员,通过友元函数showValueFromB
访问ClassB
的私有成员。
int main() {
ClassA a(10);
ClassB b(20);
b.showValue(a); // 输出 ClassA 的值
showValueFromB(b); // 输出 ClassB 的值
return 0;
}
通过这种方式,可以在不同类中声明和使用友元函数,实现跨类访问私有成员的需求。友元函数提供了访问类私有数据的灵活性,同时保持类的封装性。