运算符==在C++中如何在类之外工作

How does operator== work outside of a class in C++

本文关键字:工作 C++ 运算符      更新时间:2023-10-16

我正在阅读CppCoreGuidelines,偶然发现了一些以前不知道的东西。基本上,它说我可以在类之外重载operator==,它将以某种方式用于比较这个类的两个对象。我做到了:

#include <iostream>
class foo
{
public:
int member;
foo() : member(0) {}
};
bool operator==(const foo& lhs, const foo& rhs)
{
return lhs.member == rhs.member;
}
int main()
{
foo c1;
foo c2;
if (c1 == c2)
{
std::cout << "Even" << 'n';
}   
}

好吧,它确实有效。所以我开始在网上寻找解释。因为我可以想象,如果我试图比较一个对象,编译器会在这个类方法中搜索operator==,这对我来说是可以理解的。但这里我有一个函数,我想它可以在另一个文件中定义,它完全独立于foo类(只有它需要的参数),但它被识别为用于比较的函数。

所以现在我的问题是:编译器或者我想更具体地说,链接器是如何找到这个函数并使用它来比较这两个对象的?

假设您有一个函数bool is_equals(const foo &lhs, const foo &rhs);。编译器如何将is_equals(c1, c2)转换为对is_equals的调用?

答案是operator==完全相同。当操作数类型没有成员operator==时,编译器会尝试使用操作数类型查找非成员operator==。如果这样的东西存在,那么它就会被调用,如果它不存在,那么就不会被调用。

如果您的非成员operator==重载位于另一个文件中,而当前正在编译的文件中没有声明它的头,编译器将如何操作?答案和以前一样:如果调用is_equals而不声明存在这样的函数,会发生什么?

您得到一个编译错误。这个函数是否在另一个翻译单元中定义并不重要;如果在尝试调用函数时没有可见的声明,则会出现编译错误。

如果两个单独的文件试图用不同的实现来定义operator==,会发生什么?再次强调:如果您使用is_equal尝试此操作,也会发生同样的情况。您将违反C++的一个定义规则,因此调用了未定义的行为。希望您会得到一个链接器错误,但这并不能保证。

总之,operator==在C++中并不是一个特殊的、神奇的函数。对于函数来说,这是一个不寻常的名称,但对于编译器或链接器来说,它并没有什么特别之处。的特殊之处在于,c1 == c2被转换为对operator==(c1, c2)的调用(顺便说一句,这是你可以编写的100%合法的C++代码,尽管它只会调用非成员operator==)。但这是运算符使用的特殊之处,而不是C++函数语法。