16

我想在全局命名空间中定义一个二元运算符。操作员在另一个命名空间中定义的类上工作,并且操作员应该可以访问该类的私有成员。我遇到的问题是,当在类定义中将其设为朋友时,我不知道如何确定该全局运算符的范围。

我试过类似的东西:

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 中,而不是在全局命名空间中。

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

4

4 回答 4

17

首先,请注意您的运算符声明缺少 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 是对的——您可能应该在与其参数相同的命名空间中声明该运算符。

于 2010-02-05T13:17:09.017 回答
5

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

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() {}

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

于 2010-02-05T13:12:44.183 回答
3

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

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

于 2010-02-05T13:01:16.677 回答
3

这是可能的 - 您可以将声明符括在括号中: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 的观点,如果可能的话,最好将两者定义在同一个命名空间中。

于 2010-02-05T13:13:23.730 回答