如何在另一个 C++ 命名空间内的全局命名空间中定义朋友?

Posted

技术标签:

【中文标题】如何在另一个 C++ 命名空间内的全局命名空间中定义朋友?【英文标题】:How do I define friends in global namespace within another C++ namespace? 【发布时间】:2011-01-13 12:20:25 【问题描述】:

我想在全局命名空间中定义一个二元运算符。运营商 适用于在另一个命名空间中定义的类,操作员应该得到 访问该类的私有成员。我的问题是我没有 知道如何在类定义中使全局运算符成为朋友时对其进行作用域。

我尝试了类似的方法:

namespace NAME

    class A 
        public:
            friend A ::operator * (double lhs, const A& rhs);
        private:
            int private_var;
    ;


A operator * (double lhs, const A& rhs)

    double x = rhs.private_var;
    ...

编译器 (g++ 4.4) 不知道如何处理它。好像这条线

friend A ::operator * ()

被评估为类似(伪代码)

(A::operator)

而不是

(A) (::operator)

如果我在运算符的声明中省略 :: 编译工作,但运算符在命名空间 NAME 中,而不是在全局命名空间中。

在这种情况下如何限定全局命名空间?

【问题讨论】:

【参考方案1】:

首先,请注意您的运算符声明缺少 A 的命名空间限定:

NAME::A operator * (double lhs, const NAME::A& rhs)

然后决定性的技巧是像这样在朋友声明中添加括号,就像您在“伪代码”中提出的那样

friend A (::operator *) (double lhs, const A& rhs);

为了让它全部编译,你需要一些前向声明,到达这个:

namespace NAME

    class A;


NAME::A operator * (double lhs, const NAME::A& rhs);

namespace NAME

    class A 
        public:
            friend A (::operator *) (double lhs, const A& rhs);
        private:
            int private_var;
    ;


NAME::A operator * (double lhs, const NAME::A& rhs)

    double x = rhs.private_var;

不过,Alexander 是对的——您可能应该在与其参数相同的命名空间中声明运算符。

【讨论】:

现在有 3 个几乎相同的答案 :-) 当然,你的意思是只有三个:)【参考方案2】:

这是可能的 - 您可以将声明符括在括号中:friend A (::operator * (double lhs, const A& rhs));

您还需要前向声明类和函数。

namespace NAME class A;
NAME::A operator *(double lhs, const NAME::A& rhs);

// ...

namespace NAME

    class A 
        public:
            friend A (::operator * (double lhs, const A& rhs));
        private:
            int private_var;
    ;


NAME::A operator *(double lhs, const NAME::A& rhs) 
  //...

但我同意 Andreas 的观点,如果可能,最好将两者定义在同一个命名空间中。

【讨论】:

【参考方案3】:

这个编译,我假设没有测试它也可以工作。注意括号的使用:

namespace NAME class A; 
NAME::A operator * (double lhs, const NAME::A& rhs);

namespace NAME

    class A 
        public:
            friend A (::operator *) (double lhs, const A& rhs);
        private:
            int private_var;
    ;


NAME::A operator * (double lhs, const NAME::A& rhs)

    double x = rhs.private_var;
    return rhs;


int main() 

不过,正如 Alexander 所提到的,您的问题并没有解释为什么运算符不在命名空间 NAME 中。无论哪种方式,它都可以称为1.0 * some_A_instance。所以你可能会给自己制造不必要的麻烦。

【讨论】:

该死,你比我早了大约 20 秒。代码也几乎相同。 太好了,你拯救了我的一天。我不知道操作员可以驻留在 NAME 中并且仍然按照我想要的方式工作。【参考方案4】:

我不知道你的问题的确切答案。

但是在其参数的命名空间之外定义运算符是一个非常糟糕的主意(现在你削减了对运算符非常有用的参数依赖查找)。

【讨论】:

+1。虽然这个答案切入了问题的根源,但有一点点挑剔:如果 op* 在全局范围内,那么您不需要 ADL,因为该功能始终可用。 (我不确定,但也许 OP 不了解 ADL,因此想出了这个?)

以上是关于如何在另一个 C++ 命名空间内的全局命名空间中定义朋友?的主要内容,如果未能解决你的问题,请参考以下文章

调用在另一个命名空间中定义的 PHP 函数,不带前缀

C++ 项目相关知识命名空间

整个类范围内的 C++ 命名空间别名

使用内核命名空间 PID 从全局范围中杀死进程

C++中当未命名空间跟全局变量在一起的时候,怎么调用未命名空间里的变量

C++ Cmath.h 问题导致变量不在全局命名空间中