【问题标题】:Friend function can no longer access private data members of class after class is encapsulated in namespace类封装在命名空间后,友元函数不能再访问类的私有数据成员
【发布时间】:2018-08-18 15:42:40
【问题描述】:

我有一个名为 Circle 的类,我封装在一个命名空间中。

namespace my_name_space {
    class Circle;
}

class my_name_space::Circle {
private:
    double radius;
public:
    friend std::ostream& operator << (std::ostream &os, const Circle &c);
};

下面是实现文件中的函数:

std::ostream& operator << (std::ostream &os, const Circle &c)
{
    os << "Radius: " << c.radius;

    return os;
}

在将类封装在命名空间中之前,一切正常。现在好友功能不能再访问私有数据成员了。我不明白怎么了。

【问题讨论】:

    标签: c++ namespaces friend


    【解决方案1】:

    当您将operator &lt;&lt; 声明为Circlefriend 时,它将成为Circle 最内层封闭命名空间的成员。这意味着当您将Circle 放入命名空间my_name_space 时,operator &lt;&lt; 也将成为命名空间my_name_space 的成员。 operator&lt;&lt; 的定义不匹配,它在全球范围内定义了operator&lt;&lt;

    在类或类模板 X 中的友元声明中首先声明的名称成为 X 的最内层封闭命名空间的成员

    您可以将operator&lt;&lt; 的定义移动到命名空间my_name_space

    namespace my_name_space {
        std::ostream& operator << (std::ostream &os, const Circle &c) {
            ...
        }
    }
    

    或者,如果您仍想将operator&lt;&lt; 保留在全局范围内:

    // delcaration
    std::ostream& operator << (std::ostream &os, const my_name_space::Circle &c);
    class my_name_space::Circle {
        ...
        friend std::ostream& ::operator << (std::ostream &os, const Circle &c);
        //                   ~~
    };
    // definition
    std::ostream& operator << (std::ostream &os, const my_name_space::Circle &c) {
        ...
    }
    

    【讨论】:

    • 如果我在实现文件的顶部有一个 using 声明,using my_namespace operator 是否仍需要限定?
    • @MutatingAlgorithm 是的。 using namespace my_name_space; 成为my_name_space 的成员后不会进行声明。
    • using 声明解释了为什么使用 const Circle &amp;c 编译的 OP 代码不合格。这对我来说是个谜。
    • 您的第一个建议给出了编译器警告,而第二个则没有。
    • @OrenIshShalom 我正在使用 clang,它不会忽略任何警告。我不确定哪一个是正确的;无论如何我改变了不会引起怀疑的风格。
    猜你喜欢
    • 2021-01-02
    • 2023-03-24
    • 1970-01-01
    • 2021-11-01
    • 2021-08-16
    • 1970-01-01
    • 2016-03-16
    • 2012-02-21
    相关资源
    最近更新 更多