laocaiye 发表于 2025-3-8 17:13:52

友元成员函数

学习中仿制了下面个案例。两个了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;
}

FishC 发表于 2025-3-8 17:14:40

在您的代码中,您尝试将 `getRoom` 函数设为 `Building` 类的友元函数,但由于 `Person` 类在 `Building` 类之后才定义,因此无法在 `Building` 类中声明 `Person::getRoom()` 为友元函数。这是因为编译器在定义 `Building` 类时尚未知道 `Person::getRoom()` 函数的存在。

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

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

class Person;// 提前声明 Person 类

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

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

    string sittingRoom;

private:
    string bedRoom;
};

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

    void getRoom()
    {
      cout << building->bedRoom << endl;// 访问私有成员 bedRoom
    }
};

int main()
{
    Person p;
    p.getRoom();
    return 0;
}

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

laocaiye 发表于 2025-3-8 17:27:26

在前面提前声明了:class Person;,还是不行啊。

FishC 发表于 2025-3-8 17:28:21

laocaiye 发表于 2025-03-08 17:27
在前面提前声明了:class Person;,还是不行啊。

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

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

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

private:
    string bedRoom;

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

class Person
{
public:
    Building* building;

    Person()
    {
      building = new Building;
    }

    void getRoom()
    {
      cout << "访问: " << building->sittingRoom << endl;
      // 访问Building的私有成员bedRoom
      cout << "访问: " << building->bedRoom << endl;
    }
};

int main()
{
    Person person;
    person.getRoom();
   
    return 0;
}

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

laocaiye 发表于 2025-3-8 17:41:27

明白怎么回事了,就是说如果把类Person的成员函数当做类Building的友元函数。必须把类Person的构造实现和友元函数实现暴露在全局实现。
试验通过。

FishC 发表于 2025-3-8 17:42:15

laocaiye 发表于 2025-03-08 17:41
明白怎么回事了,就是说如果把类Person的成员函数当做 ...

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 友元成员函数