为啥我不能从不同命名空间中的朋友类更改类的私有成员?

Posted

技术标签:

【中文标题】为啥我不能从不同命名空间中的朋友类更改类的私有成员?【英文标题】:Why can't I change a private member of a class from a friend class in a different namespace?为什么我不能从不同命名空间中的朋友类更改类的私有成员? 【发布时间】:2011-05-14 16:59:49 【问题描述】:

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

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

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

g++说我不能修改成员因为它是私有的,visual studio好像觉得没问题。

我在这里做一些奇怪的非标准事情吗?为什么不能更换会员?这是代表我的问题的简化 sn-p:

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();

【问题讨论】:

【参考方案1】:
friend struct ::S;

你真正在做什么

friend struct S;

将 N::S 类(未在任何地方定义)声明为友元。

编辑:支持我的观点,即 gcc 行为是正确的,而 VC++ 存在错误。

7.3.1.2/3

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

【讨论】:

@Jacobo:因为它是有效的。你总是可以friend一个结构或类,即使它还没有被声明。 @Jacob 朋友成员不需要实际存在。当您的朋友成员是模板但没有人使用该模板时,这非常有用。加上阿舍普勒所说的。 @aschepler 可能是声明,但它不应该允许我在不是朋友的类中修改 A @Jacobo,我认为接受您的代码是 VC++ 中的一个错误。 (Como 和 Sun CC,我目前可以访问的另外两个编译器;接受它)。 @aschepler:分配无效。 OP 想知道为什么 VC++ 接受它,现在他知道它是无效的。【参考方案2】:

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

【讨论】:

【参考方案3】:

试着写出friend struct ::S;

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

【讨论】:

以上是关于为啥我不能从不同命名空间中的朋友类更改类的私有成员?的主要内容,如果未能解决你的问题,请参考以下文章

为啥派生类的朋友不能使用受保护的成员?

为啥我不能创建在与类定义相同的命名空间中定义的 C++ 类的实例?

C#中继承类为啥可以通过属性访问基类的私有字段。

为啥嵌套的子类可以访问其父类的私有成员,而孙子却不能?

为啥 PRIVATE 成员函数不能成为另一个类的友元函数?

C++ - 如何从同一个类的静态函数访问一个类的私有成员?