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



如果我创建一个类:

// 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;

我将得到一个满是编译错误的页面,以:

开头

错误C2679: binary '<<':没有找到右操作数类型为'my_class'的操作符(或者没有可接受的转换)

我可以通过添加第二个示例类来纠正这个错误:
friend std::ostream& operator <<(std::ostream& os, my_class& rhs) {
os << rhs.str;
return os;
}

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

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

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

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

对于const char*的情况,cout可用的operator <<声明为:

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

因此,当编译器分析std::cout << mc1;时,它可以从cout中推断出CharTTraits,并找到my_class::operator const char* ()mc1转换为const char*,因此重载解析成功,代码编译成功。

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

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 );

在这个重载中,不仅第一个形参依赖于模板形参,第二个形参也是如此。这意味着编译器将尝试直接从mc1推断出CharTTraitsAllocator的类型。在此步骤中没有考虑转换操作符,并且由于mc1实际上不是std::string,因此演绎失败,并且没有可能的重载,因此代码无法编译。

相关内容

  • 没有找到相关文章

最新更新