【C++】类和对象:友元函数和友元类

在这里插入图片描述

友元函数和友元类

一:什么是友元?

在C++中,友元(friend)是一种机制,允许一个类(或函数)访问另一个类的私有成员,即使这些私有成员在正常情况下是不可访问的。 友元关系是通过在一个类中声明另一个类(或函数)为友元来建立的。这样,被声明为友元的类(或函数)就可以在需要时访问该类的私有成员。

注意:

友元的存在是为了在某些特殊情况下提供灵活性和控制,但过度使用友元可能破坏封装性,因此需要谨慎使用。

友元特点:

1. 友元关系是单向的:A类是B类的友元并不代表B类是A类的友元。
2. 友元关系不可传递(继承):即如果A类是B类的友元,B类是C类的友元,那么A类不一定是C类的友元。

二:友元的使用方式

友元有以下几种形式:

友元函数:一个函数被声明为另一个类的友元函数,那么该函数可以访问该类的私有成员。这在需要进行一些与类紧密相关的操作,但又不适合将其作为类成员函数的情况下非常有用。
友元类:一个类被声明为另一个类的友元类,那么该类的所有成员函数都可以访问另一个类的私有成员。这在需要两个类之间的深度数据共享时非常有用。

(1)全局函数做友元

1. 使用方法:

调用类中的私有成员时,可以在类中声明该函数,并在前面加上friend 做友元。

2. 语法:
friend 返回值类型 全局函数();
3. 无参和有参全局函数做友元案例:
class Person {
private:
	int* m_Salary;
	int m_Age;
public:
	friend void printInfo(const Person &p); // 全局有参函数声明友元
	friend void printInfo(); // 全局无参函数声明友元
	Person() {}  // 默认构造函数
	Person(int age,int salary){ // 有参构造函数
		this->m_Age = age;
		m_Salary = new int(salary);
	}
	~Person(){ // 析构函数
		if (m_Salary != NULL){
			delete m_Salary;
			m_Salary = NULL;
		}
	}
};
//全局函数做友元 
void printInfo(const Person& p){
	cout << "年龄:" << p.m_Age << "  薪水:" << *p.m_Salary << "w" << endl;
}
// 无参全局函数做友元
void printInfo(){
	Person p1(23, 40);
	cout << "年龄:" << p1.m_Age << "  薪水:" << *p1.m_Salary << "w" << endl;
}
// 测试
int main(){
	Person p1(25,20);
	printInfo(p1);
	printInfo();
}

输出结果:

年龄:25  薪水:20w
年龄:23  薪水:40w

以上示例是全局函数 printInfo(const Person& p) 和 printInfo() 来做Person类的友元函数,可以用来访问Person类内的私有成员。

(2)成员函数做友元

1. 目的:

A类的成员函数需要访问B类的私有成员

2. 解决办法:

需要在B类中声明A类作用域下的成员函数,添加friend关键字让该成员函数做B类的友元成员函数。

3. 语法:
friend 返回值类型 类名::成员函数();
4. 注意:

友元函数的声明和实现:当一个类的成员函数作为另一个类的友元函数时,应该先在类的内部声明该成员函数,然后在类的外部实现它。 这是因为在定义友元关系时,需要确保编译器已经知道友元函数的存在和接口。类的定义在编译时的前向声明通常不足以满足这一要求,因此最佳做法是在类的内部进行函数的声明,然后在类的外部进行函数的实现。

5. 成员函数做友元案例:
//声明Person类 和 A类的visit()该成员函数将作为Person类的友元函数
class Person; 
class A { 
public:
	void visit(const Person& p); //定义该函数
};

class Person {
private:
	int* m_Salary;
	int m_Age;
public:
	Person(int age,int salary): m_Age(age),m_Salary(new int(salary)){}
	~Person(){
		if (m_Salary != NULL)
		{
			delete m_Salary;
			m_Salary = NULL;
		}
	}
	friend void A::visit(const Person& p); //声明 A 的成员函数作为友元,需要指明哪个作用域下的成员函数
};

void A::visit(const Person& p) {
	cout << "年龄:" << p.m_Age << "  薪水:" << *p.m_Salary << "w" << endl; // 通过该友元函数获取Person类的私有成员的值
}

int main()
{
	Person p1(25,20);
	A a;
	a.visit(p1);
	return 0;
}

输出结果:

年龄:25  薪水:20w

以上示例展示了如何在类的内外分别声明和实现友元函数:

  1. 声明Person类和A的成员函数:首先,在第一个类(A) 的定义之前,你需要声明另一个类(Person)。这个声明告诉编译器,有另一个类存在,即将要使用它。同时,在第一个类中声明一个成员函数作为友元函数,这个函数将访问另一个类的私有成员。
  2. 定义类:然后,定义第一个类的成员函数和其他部分。在第一个类的定义中,你只需要知道第二个类的存在,不需要关注具体的实现细节。
  3. 定义另一个类:接着,在第二个类的定义中,你可以定义它的私有成员和其他成员函数。
  4. 定义友元函数:最后,在类的定义之后,实现第一个类中声明的友元函数。这个函数将能够访问第二个类的私有成员,因为你在第一个类中声明了友元关系。

这个过程确保了类之间的依赖关系和访问权限的正确处理,使得一个类可以在需要时访问另一个类的私有成员,同时保持了良好的封装性和代码可读性。

(3)类做友元(友元类)

1. 语法:
friend class 类名;
2. 类做友元的代码案例:
class Person {
private:
	int* m_Salary;
	int m_Age;
public:
	Person(int age,int salary): m_Age(age),m_Salary(new int(salary)){}
	~Person(){
		if (m_Salary != NULL)
		{
			delete m_Salary;
			m_Salary = NULL;
		}
	}
	friend class A; // 声明 A 为友元类
};

class A {
public:
	void visit(const Person& p);
};

void A::visit(const Person& p) {
	cout << "年龄:" << p.m_Age << "  薪水:" << *p.m_Salary << "w" << endl;
}

int main()
{
	Person p1(25,20);
	A a;
	a.visit(p1);
	return 0;
}

输出结果:

年龄:25  薪水:20w

三:总结:

以上就是友元的使用形式和方式的实际操作。

注意:友元的使用应该谨慎,因为它会降低类的封装性和可维护性。过度使用友元可能会导致代码紧密耦合,增加了代码的复杂性和不可预测性。通常情况下,应该优先考虑使用类的公有接口来操作数据,而不是通过友元来直接访问私有成员。


希望大家多多支持,码字不易,若有错误请指出,共同学习!
欢迎关注🔎点赞👍收藏⭐️留言📝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值