《C++避坑神器·五》友元函数(friend)使用看这篇就够

本文详细介绍了如何通过全局函数、友元类和成员函数三种方式让函数或类访问另一个类的私有变量。特别强调了友元函数的使用规则,包括易错点和修正方法。

文章目录

概要

友元函数(friend)使用,访问类中的私有变量

技术细节

目的:让一个函数或者类访问另一个类中私有成员
友元三种实现:
(1)全局函数做友元
(2)类做友元
(3)成员函数做友元

全局函数做友元:

class Room
{
	//把全局函数声明在类中加friend修饰可以访问类中私有变量
	friend void FriendFun(Room* room);
public:
	Room()
	{
		sittingRoom = "客厅";
		bedRoom = "卧室";
	}

	string sittingRoom;

private:
	string bedRoom;
};

//全局函数
void FriendFun(Room * room)
{
	std::cout << room->bedRoom << std::endl;
}

int main()
{
	Room room;
	FriendFun(&room);
}

类做友元:

class Room
{
	//把友元类加friend修饰可以访问类中私有变量
	friend class FriendClass;
public:
	Room()
	{
		sittingRoom = "客厅";
		bedRoom = "卧室";
	}

	string sittingRoom;

private:
	string bedRoom;
};

//友元类
class FriendClass
{
public:
	FriendClass();
	void FriendFun();
	Room* room;
};

FriendClass::FriendClass()
{
	room = new Room();
}

void FriendClass::FriendFun()
{
	std::cout << room->bedRoom << std::endl;
}

int main()
{
	FriendClass fc;
	fc.FriendFun();
}

成员函数做友元(易错!):

class Room;

//友元类
class FriendClass
{
public:
	void FriendFun(Room& room);
};

class Room
{
	//把友元类加friend修饰可以访问类中私有变量
	friend void FriendClass::FriendFun(Room& room);
public:
	Room()
	{
		sittingRoom = "客厅";
		bedRoom = "卧室";
	}

	string sittingRoom;

private:
	string bedRoom;
};


void FriendClass::FriendFun(Room& room)
{
	std::cout << room.bedRoom << std::endl;
}

int main()
{
	Room room;
	FriendClass fc;
	fc.FriendFun(room);
}

FriendClass类成员函数想访问Room类中的私有成员
如果一开始把Room类的定义放在最前面而不是声明,这样会报错,因为Room类中引入了友元函数FriendFun,而FriendFun函数是在FriendClass类中定义的,在定义Room类的时候FriendFun函数还没有出现,所有会报错,这就需要把FriendClass类定义在最前面。
又由于FriendClass类的FriendFun函数引入了需要传入Room类的引用,所以必须在FriendClass类前声明Room类告诉FriendFun函数传入的Room类的引用是存在的。FriendFun函数要写在Room类之后,因为函数内部用到了bedroom变量,这是Room类中的变量,所以Room类要先定义。(如果bedRoom打红杠是因为编译器没有识别出来,但不影响编译,可以编译通过,不用理会)

如果先声明FriendClass类,在定义Room类对不对呢?
这样不对,先声明FriendClass类,说明可以在Room类中传入FriendClass类引用了,但Room类中有友元函数FriendFun,目前我只知道FriendClass类声明了,有这个类,但我不知道类中会不会有FriendFun函数,所以Room类中有友元函数FriendFun是不对的,所以不能先声明FriendClass类在定义Room类。

易错写法:!!!

class Room;

//友元类
class FriendClass
{
public:
	void FriendFun();
	Room room;
};

class Room
{
	//把友元类加friend修饰可以访问类中私有变量
	friend void FriendClass::FriendFun();
public:
	Room()
	{
		sittingRoom = "客厅";
		bedRoom = "卧室";
	}

	string sittingRoom;

private:
	string bedRoom;
};


void FriendClass::FriendFun()
{
	std::cout << room.bedRoom << std::endl;
}

int main()
{
	Room room;
	FriendClass fc;
	fc.FriendFun();
}

报错:严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C2079 “FriendClass::room”使用未定义的 class“Room”

这样写按道理没有错,为啥还报room使用未定义的类Room?
class Room;是一个前向声明,在类的声明之后,定义之前,此类是一个不完全类型,即已知前向声明过的类是一个类型,但不知道包含哪些成员。不完全类型只能以有限方式使用,不能定义该类型对象,不完全类型只能用于定义指向该类型的指针或者引用,或者用于声明(而不是定义)使用该类型作为形参类型或者返回类型的函数。
这样的话怎么修改?
把Room room改为指针类型Room *room; 同时要在FriendClass 类中写一个无参构造,里面给room分配动态内存,room=new Room; 不然room是野指针。
第二种修改就是声明带该类型作为形参的函数void FriendFun(Room &room);或void FriendFun(Room room);

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦回阑珊

一毛不嫌多,一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值