鱼C论坛

 找回密码
 立即注册
查看: 179|回复: 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`类中定义后再声明。在此情况下,友元函数应该先被完全定义后才能在别的类中被声明为友元。下面是修正后的代码:
#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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-8 17:27:26 | 显示全部楼层
在前面提前声明了:class Person;,还是不行啊。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

使用道具 举报

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


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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-3-31 06:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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