我想在全局命名空间中定义二元运算符。运营商 适用于在另一个命名空间中定义的类,操作符应该获取 访问该类的私有成员。我遇到的问题是我没有 知道在将这个全局运算符作为类定义中的朋友时如何对该全局运算符进行范围调整。
我尝试过类似的事情:
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中而不在全局命名空间中。
如何在这种情况下限定全局命名空间?
答案 0 :(得分:15)
首先,请注意您的运算符声明缺少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;
}
亚历山大是对的,但你应该将运算符声明为与其参数相同的名称空间。
答案 1 :(得分:4)
这个编译,我假设没有测试它也有效。注意使用括号:
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
。所以你可能会给自己造成不必要的麻烦。
答案 2 :(得分:3)
我不知道你问题的确切答案。
但是定义其参数的操作符外部命名空间是一个糟糕的坏主意(现在你切断了对于运算符非常有用的参数依赖查找)。
答案 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的观点,如果可能的话,最好在同一名称空间中定义它们。