💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # 简介 类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。但是,有时候需要在类的外部访问类的私有成员,怎么办? 解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。 # 友元语法 * 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的朋友。 3. 友元关系不具有传递性。类B是类A的朋友,类C是类B的朋友,但类C不一定是类A的朋友。 # c++是纯面向对象的吗? 如果一个类被声明为friend,意味着它不是这个类的成员函数,却可以修改这个类的私有成员,而且必须列在类的定义中,因此他是一个特权函数。c++不是完全的面向对象语言,而只是一个混合产品。增加friend关键字只是用来解决一些实际问题,这也说明这种语言是不纯的。毕竟c++设计的目的是为了实用性,而不是追求理想的抽象。 # 有元函数 ~~~ #define _CRT_SECURE_NO_WARNINGS #include <string> #include <iostream> using namespace std; class Building { //声明这个全局函数为友元函数 friend void GoodGay(Building &bd); public: string keting; private: string woshi; public: Building() { keting = "客厅"; woshi = "卧室"; } }; void GoodGay(Building &bd) { cout << "---: " << bd.keting << endl; cout << "---: " << bd.woshi << endl; } void test01() { Building my; GoodGay(my); }; int main() { test01(); system("pause"); return EXIT_SUCCESS; } ~~~ # 有元类 ## 通过传参访问 ~~~ #define _CRT_SECURE_NO_WARNINGS #include <string> #include <iostream> using namespace std; class Building { //声明类为有元类 friend class GoodF; public: string keting; private: string woshi; public: Building() { keting = "客厅"; woshi = "卧室"; } }; class GoodF { public: void func(Building &bd) { cout << "访问: " << bd.keting << endl; cout << "访问: " << bd.woshi << endl; } }; int main() { GoodF f; Building bd; f.func(bd); system("pause"); return EXIT_SUCCESS; } ~~~ ## 通过类内指针访问 ~~~ #define _CRT_SECURE_NO_WARNINGS #include <string> #include <iostream> using namespace std; class Building { //声明类为有元类 friend class GoodF; public: string keting; private: string woshi; public: Building() { keting = "客厅"; woshi = "卧室"; } }; class GoodF { public: Building* pbd; public: GoodF() { pbd = new Building; } //拷贝构造,防止调用默认拷贝,释放的时候重复释放同一空间 GoodF(const GoodF &f) { //申请空间,new的时候就有数据了,因为他里面的new就有了初始化 pbd = new Building; } void func() { cout << "访问: " << pbd->keting << endl; cout << "访问: " << pbd->woshi << endl; } ~GoodF() { cout << "析构函数" << endl; if (pbd != NULL) { delete pbd; } } }; int main() { GoodF f; f.func(); GoodF gf1 = f; gf1.func(); system("pause"); return EXIT_SUCCESS; } ~~~ # 类的另一个成员函数成为有元函数 ~~~ #define _CRT_SECURE_NO_WARNINGS #include <string> #include <iostream> using namespace std; //编译器知道类的声明不知道类的结构 //声明类 class Building; class GoodF { public: void func(Building &bud); }; class Building { //那个类的成员函数 是这个类的友元函数 friend void GoodF::func(Building &bud); public: string keting; private: string woshi; public: Building() { keting = "客厅"; woshi = "卧室"; } }; void GoodF::func(Building &bud) { cout << "访问: " << bud.keting << endl; cout << "访问: " << bud.woshi << endl; } int main() { Building bud; GoodF gf; gf.func(bud); system("pause"); return EXIT_SUCCESS; } ~~~