C++ 自由函数运算符==()或成员函数运算符==()哪个优先?

C++ 自由函数运算符==()或成员函数运算符==()哪个优先?,c++,c++11,c++14,c++17,C++,C++11,C++14,C++17,当自由运算符函数和成员运算符函数都已定义时,使用哪一个进行比较 #include <iostream> class A; class B; bool operator==(const A &a, const B &b){ return true; }; class A { public: bool operator==( const B &rhs ){ return false; }; }; class B { }; int main

当自由运算符函数和成员运算符函数都已定义时,使用哪一个进行比较

#include <iostream>

class A;
class B;

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

class A
{
  public:
      bool operator==( const B &rhs ){ return false; };
};

class B
{
};

int main( int argc, char **argv )
{
  A a;
  B b;
  if( a == b )
  { 
      std::cout << "a==b" << std::endl;
  }
};

我运行了几次代码,似乎成员操作符赢了。总是这样吗?

您在非成员运算符中将第一个参数类型声明为const&参数。然后给定a==b,对于要调用的非成员运算符,需要将a转换为const。另一方面,成员运算符被声明为非常量,然后它的操作数是非常量a,然后它是精确匹配,并在重载解析中获胜

如果将非成员运算符的第一个参数类型更改为A&则会出现歧义错误


或者将成员运算符限定为const,您也会得到歧义错误

您正在非成员运算符中将第一个参数类型声明为const&。然后给定a==b,对于要调用的非成员运算符,需要将a转换为const。另一方面,成员运算符被声明为非常量,然后它的操作数是非常量a,然后它是精确匹配,并在重载解析中获胜

如果将非成员运算符的第一个参数类型更改为A&则会出现歧义错误

或者将成员运算符限定为const,您也会得到歧义错误

我运行了几次代码,似乎成员操作符赢了

是的,在您的示例中,成员获胜。但不是因为你想的原因

成员函数有一个隐式的对象参数,它指向的对象参数的类型由成员函数末尾的cv限定符决定。在本例中,成员运算符没有cv限定符,因此隐式对象的类型只是A

基本上,我们有两个候选人:

bool operator==(A const&, B const&); // your non-member operator
bool operator==(A&,       B const&); // your member operator
bool operator==(A const&, B const&); // your non-member operator
bool operator==(A const&, B const&); // better member operator
成员运算符是更好的匹配,因为第一个参数是更好的匹配-我们不必对a进行更常量限定的引用

如果您让您的操作员按通常应该的方式保持常量,那么我们将有以下两个候选人:

bool operator==(A const&, B const&); // your non-member operator
bool operator==(A&,       B const&); // your member operator
bool operator==(A const&, B const&); // your non-member operator
bool operator==(A const&, B const&); // better member operator
它们是相同的,没有理由选择一个而不是另一个,我们会得到一个模糊性。没有规则规定成员函数优先于非成员函数,反之亦然

我运行了几次代码,似乎成员操作符赢了

是的,在您的示例中,成员获胜。但不是因为你想的原因

成员函数有一个隐式的对象参数,它指向的对象参数的类型由成员函数末尾的cv限定符决定。在本例中,成员运算符没有cv限定符,因此隐式对象的类型只是A

基本上,我们有两个候选人:

bool operator==(A const&, B const&); // your non-member operator
bool operator==(A&,       B const&); // your member operator
bool operator==(A const&, B const&); // your non-member operator
bool operator==(A const&, B const&); // better member operator
成员运算符是更好的匹配,因为第一个参数是更好的匹配-我们不必对a进行更常量限定的引用

如果您让您的操作员按通常应该的方式保持常量,那么我们将有以下两个候选人:

bool operator==(A const&, B const&); // your non-member operator
bool operator==(A&,       B const&); // your member operator
bool operator==(A const&, B const&); // your non-member operator
bool operator==(A const&, B const&); // better member operator

它们是相同的,没有理由选择一个而不是另一个,我们会得到一个模糊性。没有规则将成员函数优先于非成员函数,反之亦然。

这两个运算符具有不同的签名。当a是常量对象时,请尝试a==b。这两个运算符具有不同的签名。当a是常量对象时,尝试a==b。因此,constexpr auto a::operator==const b&rhs const noexcept->bool{return false;}因此,constexpr auto a::operator==const b&rhs const noexcept->bool{return false;}