类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。但是,有时候需要在类的外部访问类的私有成员,怎么办?

解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。这一点从现实生活中也可以很好的理解:

比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。

程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。

1. 友元语法

  • friend关键字只出现在声明处
  • 其他类、类成员函数、全局函数都可声明为友元
  • 友元函数不是类的成员,不带this指针
  • 友元函数可访问对象任意成员属性,包括私有属性
class Building;
//友元类
class MyFriend{
	public:
		//友元成员函数
		void LookAtBedRoom(Building& building);
		void PlayInBedRoom(Building& building);
};
class Building{
		//全局函数做友元函数
		friend void CleanBedRoom(Building& building);
	#if 0
		//成员函数做友元函数
		friend void MyFriend::LookAtBedRoom(Building& building);
		friend void MyFriend::PlayInBedRoom(Building& building);
	#else	
		//友元类
		friend class MyFriend;
	#endif
	public:
		Building();
	public:
		string mSittingRoom;
	private:
		string mBedroom;
};

void MyFriend::LookAtBedRoom(Building& building){
	cout << "我的朋友参观" << building.mBedroom << endl;
}
void MyFriend::PlayInBedRoom(Building& building){
	cout << "我的朋友玩耍在" << building.mBedroom << endl;
}

//友元全局函数
void CleanBedRoom(Building& building){
	cout << "友元全局函数访问" << building.mBedroom << endl;
}

Building::Building(){
	this->mSittingRoom = "客厅";
	this->mBedroom = "卧室";
}

int main(){

	Building building;
	MyFriend myfriend;

	CleanBedRoom(building);
	myfriend.LookAtBedRoom(building);
	myfriend.PlayInBedRoom(building);

	system("pause");
	return EXIT_SUCCESS;
}

友元类注意:

  1. 友元关系不能被继承。
  2. 友元关系是单向的,类A是类B的朋友,但类B不一定是类A的朋友。
    友元关系不具有传递性。类B是类A的朋友,类C是类B的朋友,但类C不一定是类A的朋友。

c++是纯面向对象的吗?

如果一个类被声明为friend,意味着它不是这个类的成员函数,却可以修改这个类的私有成员,而且必须列在类的定义中,因此他是一个特权函数。c++不是完全的面向对象语言,而只是一个混合产品。增加friend关键字只是用来解决一些实际问题,这也说明这种语言是不纯的。毕竟c++设计的目的是为了实用性,而不是追求理想的抽象。
— Thinking in C++