鱼C论坛

 找回密码
 立即注册
查看: 240|回复: 5

[已解决]友元成员函数

[复制链接]
发表于 2025-3-8 17:13:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
学习中仿制了下面个案例。两个了Building、Person。在Building类中,把Person类的成员函数getRoom当做Building类的友元函数。
但是在访问Building 类的私有属性bedRoom时,不让访问。一脸懵逼,没看出来哪里错了。

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

class Building
{
friend void Person::getRoom();

public:
        Building()
        {
                bedRoom = "卧室";
                sittingRoom = "客厅";
        }

        string sittingRoom;

private:
        string bedRoom;
};

class Person
{
public:
        Building* building;
        Person()
        {
                building = new Building;
        }

        void getRoom()
        {
                cout << building->bedRoom << endl;
                cout << building->sittingRoom << endl;
        }
};

void test2()
{
        Person p;
        p.getRoom();
}

int main()
{
        test2();
        system("pause");

        return 0;
}
最佳答案
2025-3-8 17:28:21
laocaiye 发表于 2025-03-08 17:27
在前面提前声明了:class Person;,还是不行啊。


抱歉,上面的回答确实不够完整,让我们重新整理下代码逻辑。问题的根源在于您试图在`Building`类中引用`Person`类的`getRoom`方法,但此时`Person`类尚未完整声明。这需要将友元声明移到`Building`类外,也就是在`Person`类中定义后再声明。在此情况下,友元函数应该先被完全定义后才能在别的类中被声明为友元。下面是修正后的代码:

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;

  4. class Building
  5. {
  6. public:
  7.     string sittingRoom;
  8.    
  9.     Building()
  10.     {
  11.         bedRoom = "卧室";
  12.         sittingRoom = "客厅";
  13.     }

  14. private:
  15.     string bedRoom;

  16.     // 让 Person 成为这个类的友元,以便其成员函数 getRoom 可以访问私有成员
  17.     friend class Person;
  18. };

  19. class Person
  20. {
  21. public:
  22.     Building* building;

  23.     Person()
  24.     {
  25.         building = new Building;
  26.     }

  27.     void getRoom()
  28.     {
  29.         cout << "访问: " << building->sittingRoom << endl;
  30.         // 访问Building的私有成员bedRoom
  31.         cout << "访问: " << building->bedRoom << endl;
  32.     }
  33. };

  34. int main()
  35. {
  36.     Person person;
  37.     person.getRoom();
  38.    
  39.     return 0;
  40. }
复制代码


在这个调整中,`Building`类的朋友改为整个`Person`类,这样`Person`类中的全部方法都能访问`Building`类的私有成员。请确保友元类或函数被提交完全定义后再被其访问目标的类声明。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-3-8 17:14:40 | 显示全部楼层
在您的代码中,您尝试将 `getRoom` 函数设为 `Building` 类的友元函数,但由于 `Person` 类在 `Building` 类之后才定义,因此无法在 `Building` 类中声明 `Person::getRoom()` 为友元函数。这是因为编译器在定义 `Building` 类时尚未知道 `Person::getRoom()` 函数的存在。

为了解决这个问题,您可以将 `Person` 类的定义移到 `Building` 之前,或者将友元声明的地方调整一下。这里有一个可能的解决方案:

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;

  4. class Person;  // 提前声明 Person 类

  5. class Building
  6. {
  7.     friend void Person::getRoom();  // 让 Person::getRoom() 成为 Building 类的友元

  8. public:
  9.     Building()
  10.     {
  11.         bedRoom = "卧室";
  12.         sittingRoom = "客厅";
  13.     }

  14.     string sittingRoom;

  15. private:
  16.     string bedRoom;
  17. };

  18. class Person
  19. {
  20. public:
  21.     Building* building;
  22.     Person()
  23.     {
  24.         building = new Building;
  25.     }

  26.     void getRoom()
  27.     {
  28.         cout << building->bedRoom << endl;  // 访问私有成员 bedRoom
  29.     }
  30. };

  31. int main()
  32. {
  33.     Person p;
  34.     p.getRoom();
  35.     return 0;
  36. }
复制代码


通过提前声明 `Person` 类,并在 `Building` 类中正确地引用 `Person::getRoom()`,可以解决您面临的问题。请注意,使用 `backcolor=#eee` 来表示行内代码时,需要根据您的环境调整。希望这个解释对您有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-8 17:27:26 | 显示全部楼层
在前面提前声明了:class Person;,还是不行啊。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-8 17:28:21 | 显示全部楼层    本楼为最佳答案   
laocaiye 发表于 2025-03-08 17:27
在前面提前声明了:class Person;,还是不行啊。


抱歉,上面的回答确实不够完整,让我们重新整理下代码逻辑。问题的根源在于您试图在`Building`类中引用`Person`类的`getRoom`方法,但此时`Person`类尚未完整声明。这需要将友元声明移到`Building`类外,也就是在`Person`类中定义后再声明。在此情况下,友元函数应该先被完全定义后才能在别的类中被声明为友元。下面是修正后的代码:

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;

  4. class Building
  5. {
  6. public:
  7.     string sittingRoom;
  8.    
  9.     Building()
  10.     {
  11.         bedRoom = "卧室";
  12.         sittingRoom = "客厅";
  13.     }

  14. private:
  15.     string bedRoom;

  16.     // 让 Person 成为这个类的友元,以便其成员函数 getRoom 可以访问私有成员
  17.     friend class Person;
  18. };

  19. class Person
  20. {
  21. public:
  22.     Building* building;

  23.     Person()
  24.     {
  25.         building = new Building;
  26.     }

  27.     void getRoom()
  28.     {
  29.         cout << "访问: " << building->sittingRoom << endl;
  30.         // 访问Building的私有成员bedRoom
  31.         cout << "访问: " << building->bedRoom << endl;
  32.     }
  33. };

  34. int main()
  35. {
  36.     Person person;
  37.     person.getRoom();
  38.    
  39.     return 0;
  40. }
复制代码


在这个调整中,`Building`类的朋友改为整个`Person`类,这样`Person`类中的全部方法都能访问`Building`类的私有成员。请确保友元类或函数被提交完全定义后再被其访问目标的类声明。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-8 17:41:27 | 显示全部楼层
明白怎么回事了,就是说如果把类Person的成员函数当做类Building的友元函数。必须把类Person的构造实现和友元函数实现暴露在全局实现。
试验通过。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-8 17:42:15 | 显示全部楼层
laocaiye 发表于 2025-03-08 17:41
明白怎么回事了,就是说如果把类Person的成员函数当做 ...


是的,你理解得非常正确!当你想让某个类的方法成为另一个类的友元时,如果友元方法定义在另一个类中,编译器需要在该类方法定义之前知道该方法的具体形式。因此通常将方法定义放在之前,或者将类本身声明为友元类,以允许其所有成员函数访问另一个类的私有成员。这确保了编译器在处理友元关系时能够正确解析相关的符号。继续加油,如果还有其他问题,随时可以提出!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-10 00:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表