c++ - 将 std 字符串访问器与 ostream 运算符 << 一起使用

标签 c++ string overloading iostream accessor

如果我创建一个类:

// First Example
#include <iostream>
#include <string>

class my_class {
  std::string str;
public:
  my_class(const char* s = "") : str(s) {}

  operator const char* () const { return str.data(); } // accessor
};

my_class mc1{"abc"};
std::cout << mc1; // Calls the char* accessor and successfully writes "abc" to screen output.

如果我这样修改类:

// Second Example
class my_class {
  std::string str;
public:
  my_class(const char* s = "") : str(s) {}

  operator std::string () const { return str; } // accessor
};

my_class mc1{"abc"};
std::string mystring = mc1; // Calls the string accessor
std::cout << mystring; // Also successfully writes "abc" to screen output.

但是,如果我尝试调用:

std::cout << mc1;

我会得到一个充满编译错误的页面,开头是:

error C2679: binary '<<': no operator found which takes a right-hand operand of type 'my_class' (or there is no acceptable conversion)

我可以通过添加到第二个示例类来更正此错误:

  friend std::ostream& operator <<(std::ostream& os, my_class& rhs) {
    os << rhs.str;
    return os;
  }

我主要是从该问题的建议解决方案之一中抄录的。但我不明白为什么有必要使用字符串访问器而不是 char* 访问器。

我期望成功编译并输出 mc1.str 的值,否则我会期望在第一个示例中尝试使用 char* 访问器函数时出现相同的错误。相反,我仅在第二个示例中收到了 C2679。

更新:我看到在 ostream 中使用强制转换运算符,例如std::cout << (std::string)mc1; , 将显式调用字符串访问器并将字符串写入屏幕。

最佳答案

发生这种情况是因为函数的定义方式。

对于 const char*案例,operator <<cout可用于声明为:

template< class CharT, class Traits >
basic_ostream<CharT, Traits>&
    operator<<( basic_ostream<CharT, Traits>& os, const char* s );

所以,当编译器分析std::cout << mc1; , 它可以推断出什么 CharTTraits来自cout , 它会找到 my_class::operator const char* ()转换 mc1进入 const char* , 因此重载解析成功并且代码编译。

当你切换到 operator std::string () 时并使用 std::cout << mc1; ,您现在需要调用 std::string operator << 过载,声明为:

template< class CharT, class Traits, class Allocator >
std::basic_ostream<CharT, Traits>&
    operator<<( std::basic_ostream<CharT, Traits>& os,
                const std::basic_string<CharT, Traits, Allocator>& str );

在这个重载中,不仅第一个参数依赖于模板参数,第二个参数也是如此。这意味着编译器将尝试推断 CharT 的类型, TraitsAllocator来自 mc1直接地。在此步骤中不考虑转换运算符,因为 mc1实际上不是 std::string ,推导失败,并且没有可能的重载,因此代码无法编译。

关于c++ - 将 std 字符串访问器与 ostream 运算符 << 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74436602/

相关文章:

C - 垃圾字符,即使有空终止符,结构

c++ - - 内联函数 g++4.9.2 中的 Warray-bounds 虚假警告

c++ - 实现部分写入压缩数据的存储编写器

c++ - 在 DOS 中添加按钮

比较 2 个字符串并保存结果

matlab - 如何在 Matlab 中正确重载 size() 方法/运算符

c++ - 我应该在 include 语句末尾添加分号吗?

ruby - 查看 ruby​​ 字符串中是否有空格

c# - 当唯一的区别是可选参数时,为什么 C# 允许重载?

java - 重载和覆盖方法中的多态性