为什么我无法从不同命名空间中的友元类更改类的私有成员?

Why can't I change a private member of a class from a friend class in a different namespace?

本文关键字:友元 成员 命名空间 为什么      更新时间:2023-10-16

我发现从朋友类访问类的私人成员时遇到问题。

保存我要更改的私有成员的类和进行更改的类位于不同的命名空间中。

友元类

是在保存数据的类之后定义的,因此我尝试在命名空间之外转发声明友元类。

g++说我不能修改成员,因为它是私有的,Visual Studio似乎认为它很好。

我在这里做一些奇怪的非标准的事情吗?为什么我不能更改会员?这是一个简化的代码片段,代表我的问题:

struct S;
namespace N
{
    class A
    {
        int m;
    public:
        A():m(5){};
        friend struct S;
    };
}
using namespace N;
struct S
{
    A& a;
    S(A& a):a(a) {}
    void changeA(){ a.m = 9; }
};
int main()
{
    A a;
    S s(a);
    s.changeA();
}
friend struct ::S;

你真正在做什么

friend struct S;

将类 N::S 声明为友元(无处定义)。

编辑:为了支持我的想法,即 gcc 行为是正确的,VC++ 有一个错误。

7.3.1.2/3

如果非本地类中的friend声明首先声明一个类或 函数 友元类或函数是最内层的成员 封闭命名空间。[...] 当寻找事先声明 由 friend 声明引入的类或函数,作用域在 不考虑最里面的封闭命名空间范围。

因为friend struct S;声明N::S类,但你需要::S类。

试着写出friend struct ::S; .

目前,假设不存在N::S。此修复指定全局命名空间,有点类似于 Linux 路径上的前导/指定文件系统根目录的方式。