【C++ OOP 03 友元】各种友元例子以及如何类外写成员函数

【友元】

在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术

友元的目的就是让一个函数或者类 访问另一个类中私有成员

友元的关键字为 friend

友元的三种实现

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元

全局函数友元

新建一个Building类,里面有客厅(public)和卧室(private)两个属性

class Building {

//行为
public:
	//构造函数
	Building() {
		m_SittingRoom = "客厅";
		m_BadRoom = "卧室";
	}

//属性
public:
	string m_SittingRoom;
private:
	string m_BadRoom;
};

int main() {
	system("pause");
	return 0;
}

在main外部(全局)创建一个函数goodGay,分别访问两个属性。

使用test01函数测试,当然私有属性要访问时会报错

class Building {

//行为
public:
	//
	Building() {
		m_SittingRoom = "客厅";
		m_BadRoom = "卧室";
	}

//属性
public:
	string m_SittingRoom;
private:
	string m_BadRoom;
};

void goodGay(Building *building) {
	cout << "好基友正在访问: " << building->m_SittingRoom << endl;
	//cout << "好基友正在访问: " << building->m_BedRoom << endl;
}

void test01() {
	Building building;
	goodGay(&building);
}

int main() {

	test01();

	system("pause");
	return 0;
}

这时,需要将void goodGay(Building *building)添加到Building类的开头,并以关键字‘friend’修饰

#include<iostream>
using namespace std;
#include<string> 

class Building {

	//声明友元
	friend void goodGay(Building* building);

//行为
public:
	//
	Building() {
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}

//属性
public:
	string m_SittingRoom;
private:
	string m_BedRoom;
};

void goodGay(Building *building) {
	cout << "好基友正在访问: " << building->m_SittingRoom << endl;
	cout << "好基友正在访问: " << building->m_BedRoom << endl;
}

void test01() {
	Building building;
	goodGay(&building);
}

int main() {
	test01();

	system("pause");
	return 0;
}

由此,友元全局函数goodGay便可以访问Building类中的私有属性

类友元

例子的框架与之前类似

只是这次我们需要创建一个GoodGay类去访问

补充知识点:类外写成员函数

例如,现在有一个Building类

class Building
{
public:
	Building();
public:
	string m_SittingRoom; //客厅
private:
	string m_BedRoom;//卧室
};

int main(){
    
	system("pause");
	return 0;
}

该类中的构造函数(也是成员函数之一)只是声明还没有实现,我们可以在类外对其进行实现

class Building
{
public:
	Building();
public:
	string m_SittingRoom; //客厅
private:
	string m_BedRoom;//卧室
};

//类外实现成员函数
//"xxx :: xx函数",xxx表示声明了函数的作用域
Building::Building()
{
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}

int main(){
    
	system("pause");
	return 0;
}

例子

根据上面的方法,我们在GoodGay类和Building类外面分别实现其构造函数

#include<iostream>
using namespace std;
#include<string> 

class Building;
class goodGay
{
public:

	goodGay();
	void visit();

private:
	Building *building;
};


class Building
{
	//告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容
	friend class goodGay;

public:
	Building();

public:
	string m_SittingRoom; //客厅
private:
	string m_BedRoom;//卧室
};

//类外实现构造函数Building()
//作用域在Building类下
Building::Building()
{
	this->m_SittingRoom = "客厅";
	this->m_BedRoom = "卧室";
}

//类外实现goodGay构造函数
//作用域在goodGay类下
goodGay::goodGay()
{
	//在堆区创建建筑物对象
    //goodGay类中的Building *building指向该对象
    building = new Building;
}

//类外实现goodGay的成员函数
//作用域在goodGay类下
void goodGay::visit()
{
	cout << "好基友正在访问" << building->m_SittingRoom << endl;
	cout << "好基友正在访问" << building->m_BedRoom << endl;
}

void test01()
{
	goodGay gg;
	gg.visit();

}

int main(){

	test01();

	system("pause");
	return 0;
}

GoodGay类能访问Building类的私有属性的关键也是使用友元

即在Building类开头用‘friend’修饰

class Building
{
	//告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容
	friend class goodGay;

public:
    ...

成员函数友元

例子

#include<iostream>
using namespace std;
#include<string> 

class Building;
class goodGay
{
public:
	goodGay();
	void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容
	void visit2(); 

private:
	Building *building;
};

class Building
{
	//告诉编译器  goodGay类中的visit成员函数 是Building好朋友,可以访问私有内容
	friend void goodGay::visit();

public:
	Building();

public:
	string m_SittingRoom; //客厅
private:
	string m_BedRoom;//卧室
};

//类外实现构造函数Building()
//作用域在Building类下
Building::Building()
{
	this->m_SittingRoom = "客厅";
	this->m_BedRoom = "卧室";
}

//类外实现构造函数goodGay()
//作用域在goodGay类下
goodGay::goodGay()
{
	building = new Building;
}

//类外实现成员函数visit()
//作用域在goodGay类下
void goodGay::visit()
{
	cout << "好基友正在访问" << building->m_SittingRoom << endl;
	cout << "好基友正在访问" << building->m_BedRoom << endl;
}

//类外实现成员函数visit2()
//作用域在goodGay类下
void goodGay::visit2()
{
	cout << "好基友正在访问" << building->m_SittingRoom << endl;
	//cout << "好基友正在访问" << building->m_BedRoom << endl;
}

void test01()
{
	goodGay  gg;
	gg.visit();
}

int main(){    
	test01();

	system("pause");
	return 0;
}

技巧

如果之后要用到某个类,但是该类的细节还没有写,可以先写个占位的代码

class Building;
class goodGay{
public:
	goodGay();
	void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容
	void visit2(); 

private:
    //用到了但还没写
	Building *building;
};

...
    //之后再定义
class Building{
    
}
posted @ 2023-01-27 22:09  dayceng  阅读(54)  评论(0编辑  收藏  举报