C++中运算符会使用哪个重载?

3

众所周知,你不能使用 + 运算符连接两个字符串文字。

#include <iostream>

int main() {
  std::cout << "hello " + "world";
}
// Error

这里发生的情况是你试图添加2个char*,这是一个错误。但是,你可以将字符串字面量添加到std::string中。
#include <iostream>

int main() {
  std::string s = "hello ";
  std::cout << s + "world";
}
// Fine, prints hello world

但我发现下面的代码也是有效的。

#include <iostream>

int main() {
  std::string s = "world";
  std::cout << "hello " + s;
}
// Fine, prints hello world

我想象在上面的例子中,您正在尝试将std :: string添加到char *中,但它可以正常工作。 我认为它可能只是使用+运算符的std :: string重载。我的问题是这里究竟发生了什么,以及在出现两个具有完全有效重载的不同类相加的情况下,运算符如何决定使用哪种重载。

3
operator+ 对于 std::string 有多个重载。 - Jarod42
这是利用运算符重载可以作为自由函数而不仅仅是类成员方法实现的几种情况之一。 - Nathan Pierson
2个回答

8
这里正在发生的事情是尝试添加2个char*,这是一个错误。
更准确地说,您正在尝试添加两个数组,每个数组都会衰减为const char*。
我的问题是这里到底发生了什么。
您正在使用这些重载:
std::string
operator+(const std::string& lhs, const char* rhs);

std::string
operator+(const char* lhs, const std::string& rhs);

运算符重载是如何决定使用哪个重载的?
它使用与普通函数相同的重载解析。由于重载解析非常复杂,完整和精确的描述无法适应此答案。
简而言之:有一个名称相同的所有函数列表。这是重载集。如果所有参数(在运算符重载的情况下是操作数)可以转换为函数的形式参数,则该函数是重载解析的可行候选项。候选者按一组规则排名。需要“较少”转换的候选者排名较高。如果一个候选者明显是最高排名的候选者,则将调用该重载;否则将出现错误。

这段代码难道不应该使用 const std::string& 重载吗? - Nathan Pierson
@NathanPierson 是的。已修复。 - eerorika
我原本以为它只能使用左操作数的重载,但这样更有意义,似乎非常有用。就重载决议而言,如果我有两个同样有效的来自不同类的重载,那么它将无法选择一个并且会出现错误? - Geobor
@Geobor 是的,这个程序将无法正常运行。 - eerorika

3

运算符优先级 : + 的优先级高于 <<,因此该行被解析为:

(std::cout <<  ("hello " + s) );

这里的第四个是operator+(const char*,const std::string&),具体请参考https://en.cppreference.com/w/cpp/string/basic_string/operator%2B

也许你会有些惊讶,因为通常运算符是成员函数,这意味着左操作数必须是std::string。但是,并非总是如此,运算符可以是自由函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接