3

我认为这个例子最能说明我的问题:

namespace N {

    class C {
    public:
        friend bool operator==(const C& c, const C& x) {
            return true;
        }
        friend bool f(const C& c, const C& x) {
            return true;
        }
    };

    class D {
    public:
        bool operator==(const D& x) {
            bool a = C{} == C{};      // this works
            return true;
        }
        bool f(const D& x) {
            bool a = f(C{}, C{});     // this does not work
            return true;
        }
    };
}

我一直认为重载运算符就像函数一样,除了“调用语法”,如果你愿意的话。我只是在 ADL 或名称查找规则中注意到了上述差异(我不知道是哪一个)。

有人可以解释为什么bool operator==(const C& c, const C& x)找到但bool f(const C& c, const C& x)不是吗?

4

1 回答 1

2

躲起来D::f;如果您将后者重命名为并调整调用,则它可以正常工作(表明可以正常找到访问该函数)。 C::fC::g

您的代码实际上并没有直接调用运算符函数,但这是由语言为您完成的。因此,您没有使用运算符函数的名称,因此不应用名称隐藏。

如果您编写operator==(C{}, C{})(而不是),那么您将看到与(演示C{} == C{})相同的行为。f(C{}, C{})

所以,当你说“我一直认为重载的运算符就像函数一样,除了'调用语法',如果你愿意的话”,你已经一针见血了。


这里有一些标准的给你:

[C++11: 13.5/4]:运算符函数通常不直接调用;相反,它们被调用来评估它们实现的运算符 (13.5.1 – 13.5.7)。但是,可以使用operator-function-id作为函数调用语法 (5.2.2) 中的函数名称来显式调用它们。[ 例子:

complex z = a.operator+(b); // complex z = a+b;
void* p = operator new(sizeof(int)*n);

—结束示例]

[C++11: 3.3.7/4]: [..] 4) 在成员函数中声明的名称隐藏了同名的声明,其范围扩展到或超过成员函数类的末尾。[..]

[C++11: 3/4]:名称是标识符(2.11)、operator-function-id (13.5)、literal-operator-id (13.5.8)、conversion-function-id (12.3.2) 或template-id (14.2)的使用表示实体或标签(6.6.4, 6.1)。

(这里的 [qualified] operator-function-id::N::C::operator==.)

于 2014-06-11T16:53:36.930 回答