您重载的函数的左侧为std::ostream&,右侧为const std::string&。这就是你调用函数的方式:
fl << "!!!Hello World!!!" << endl;
左侧完美匹配,但右侧不匹配。您传递的字符串不是std::string,而是char const* 类型的对象。即使存在从 char const* 到 const std::string& 的可行转换,您所做的自定义重载也不会被调用,因为实际上存在完美匹配其他地方。
完美匹配的重载是命名空间std中的重载,其签名为:
namespace std { // Simplification:
std::ostream& operator<<(std::ostream& os, char const* str);
}
这是一个更好的匹配,因为不需要对右手参数进行转换。另一个原因是因为 ADL 或 Argument Dependent Lookup。通常,您必须从这些命名空间之外显式限定来自其他命名空间(如std)的名称或函数,但是当涉及到 ADL 时,如果编译器可以找到一个函数,该函数从中获取用户定义类型的类相同的命名空间,调用所述函数将不需要来自该命名空间之外的显式限定。因此以上等价于:
std::operator<<(f1, "!!!Hello World!!!") << std::endl;
您可以在使用std::getline() 时看到这一点。即使我们不使用using namespace std 或using std::getline,以下是格式正确的:
getline(std::cin, line);
因为std::cin 与函数std::getline() 在同一个命名空间中,所以您不需要将std:: 附加到函数调用中。
因此,要调用您的重载,必须有更好的匹配。您可以通过显式创建std::string 来强制执行此操作:
fl << std::string("!!!Hello World!!!") << endl;
您的重载被调用,而不是命名空间std 中的重载,因为封闭命名空间中的重载在std 等外部命名空间之前被考虑。但这不仅不直观,还会引发其他问题。
您的函数需要返回类型 std::ostream& 而不是 void 并具有 return os 语句,以便您可以链接 << endl 表达式。
在您的函数内部,您正在对os << str 行执行无限递归。有很多方法可以解决这个问题,最简单的方法是执行 os << str.c_str(),以便调用命名空间 std 中的 char const* 重载。
您的方法不是最好的方法,因此要获得更完整和更好的解决方案,请查看此线程中的其他答案和 cmets。