如果我創建一個類:
// 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:二進制“<<”:未找到采用“my_class”型別右手運算元的運算子(或沒有可接受的轉換)
我可以通過添加到第二個示例類來更正此錯誤:
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;,將顯式呼叫字串訪問器并將字串寫入螢屏。
uj5u.com熱心網友回復:
發生這種情況是因為函式的定義方式。
對于這種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;,它可以推斷出 whatCharT和Traitsare from cout,并發現my_class::operator const char* ()轉換mc1為 a const char*,因此多載決議成功并且代碼編譯。
當您切換到 havingoperator std::string ()和 usestd::cout << mc1;時,您現在需要呼叫std::string多載 for 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,Traits和Allocatorfrom的型別mc1。在此步驟中沒有考慮轉換運算子,并且由于mc1實際上不是std::string,推導失敗并且您沒有可能的多載,因此代碼無法編譯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/533915.html
上一篇:從dart中的給定字串中洗掉\n
