1

Stroustrup 写道:

考虑一个二元运算符@。如果 x 属于 X 类型并且 y 属于 Y 类型,则 x@y 解析如下:

• 如果X 是一个类,则查找operator@ 作为X 的成员或作为X 的基的成员;和

• 在围绕x@y 的上下文中寻找operator@ 的声明;和

• 如果 X 在命名空间 N 中定义,则在 N 中查找 operator@ 的声明;和

• 如果 Y 在命名空间 M 中定义,则在 M 中查找 operator@ 的声明。

可以找到多个 operator@s 的声明,并且使用重载解析规则(第 12.3 节)来找到最佳匹配(如果有)。仅当运算符具有至少一个用户定义类型的操作数时,才应用此查找机制。因此,将考虑用户定义的转换(§18.3.2、§18.4)。请注意,类型别名只是同义词,而不是单独的用户定义类型(第 6.5 节)。一元运算符以类似方式解析。

请注意,在运算符查找中,成员没有优先于非成员。这与查找命名函数不同

那么大胆的表达是什么意思。如果类有成员并且同时有可以在上下文中使用的非成员函数,那么不优先考虑成员吗?例如

class A
{
public:
    bool operator==(const A&)
    {
        return true;
    }
};

bool operator==(const A&, const A&)
{
    return true;
}

int main()
{
    A a, b;
    a == b;
}

我认为(并且编译器同意我的观点:))应该调用成员函数,但如上所述,不应优先考虑成员运算符。那么,这句话究竟是什么意思 Stroustrup 呢?

4

1 回答 1

2

您的代码只能编译,因为您的运算符在此上下文中不等效。一种优于另一种,根据隐式转换顺序排序规则。

请注意,您的成员运算符的第一个(左)参数缺少 const 限定。它实际上代表bool operator==(A&, const A&).

由于您的abinmain未声明为,因此对于成员const运算符,左侧操作数的隐式转换序列更短(更好)。它不需要从到的资格转换。这就是使它成为更好的候选人的原因。这就是选择您的成员函数版本的原因。aAconst A

要使两个版本等效,您必须添加const到您的成员运算符声明

class A
{
public:
    bool operator==(const A&) const
    {
        return true;
    }
};

这将立即使您的a == b比较模棱两可。

于 2015-04-22T21:21:26.007 回答