2014-10-16 114 views
8

爲什麼C++將字符串文字轉換爲布爾值而不是字符串?重載布爾/字符串歧義

#include <iostream> 

using namespace std; 

class A 
{ 
    public: 
     A(string v) 
     { 
      cout << v; 
     } 

     A(bool v) 
     { 
      cout << v; 
     } 
}; 

int main() 
{ 
    A("hello"); 
    return 0; 
} 

輸出:1

是因爲編譯器是不是足夠聰明,使從字符*串跳躍和而只是假設布爾是最接近的指針?我唯一的選擇是創建一個明確的char *構造函數,它基本上和字符串構造函數完全一樣嗎?

+1

我通常更喜歡明確的轉換。隱式轉換有這樣的陷阱。請參閱http://stackoverflow.com/q/2346083/10077 – 2014-10-16 21:18:23

+0

我不確定但是:兩種轉換都是可能的(將指針轉換爲布爾檢查空指針)。但轉換爲布爾是*內置*轉換,而字符串是*用戶定義的* convesion(通過隱式c'tor)。現在,如果我沒有記錯,內置插件比用戶定義的優先級更高。 – leemes 2014-10-16 21:19:03

+1

可能重複的[C++方法重載不工作](http://stackoverflow.com/questions/14770252/c-method-overload-not-working) – 2014-10-16 21:57:26

回答

12

如果有C++ 11可以使用一個委派構造:

A(char const* s) : A(std::string(s)) { } 

其原因被選擇在一個用於std::string轉換構造函數布爾是因爲轉換從char const*bool是標準轉換,而std::string是用戶定義的轉換。標準轉換的排名高於用戶定義的轉化。

3

隨着

A(string("hello")); 

它會給預期的結果。

這是爲什麼?

這是因爲標準的轉化:

  • 「你好」被理解爲一個const char*指針
  • 這個指針可以被轉換爲標準的bool(第4.12:「的prvalue (...)指針(...)類型可以轉換爲bool類型的prvalue。「
  • 從」hello「到string的轉換不被考慮,因爲標準的第12.3節解釋爲」類對象的類型轉換可以由構造函數和轉換函數指定。這些轉換被稱爲用戶定義的轉換「和」他們是毫不含糊的地方用戶定義的轉換隻適用」你會不會有bool構造的std::string轉換將被隱含完成。

如何讓你的預期

只需添加缺少的構造函數的字符串litterals什麼?

A(const char* v) 
{ 
    cout << v; // or convert v to string if you want to store it in a string member 
} 

當然,不是從頭開始重寫構造函數,而是可以在另一個答案中選擇由0x499602D2建議的委託。

+0

是的,但我不想輸出'字符串(。每次。我唯一的選擇是創建一個將'char const *'作爲參數的構造函數嗎? – RPGillespie 2014-10-16 21:31:01

+0

是的!我完成了額外的解釋。 – Christophe 2014-10-16 22:07:59

2

當選擇一個重載方法這是編譯器試圖順序:

  1. 精確匹配
  2. 促進
  3. 標準數值轉換
  4. 用戶定義的運算符

指針不會促銷到bool,但它確實轉換爲bool。 A char*使用std運營商轉換爲std::string。請注意,如果char*在此列表中使用相同的編號轉換爲boolstd::string這將是不明確的編譯器應該選擇哪種方法,因此編譯器會引發「模糊過載」錯誤。

我會把我的體重放在0x499602D2的解決方案後面。如果你有C++ 11,最好的辦法是打電話給:A(char* s) : A(std::string(s)){} 如果你沒有C++ 11,那麼我會創建一個A(char* s)的構造函數,並將構造函數的邏輯抽象成一個方法並從兩個方法中調用該方法構造函數。

http://www.learncpp.com/cpp-tutorial/76-function-overloading/

2

最近我通過這個問題也讓我分享另一種方式。

您可以將bool構造函數更改爲unsigned char。所以字符串文字的衰減和隱含轉換不會發生,並且std::string構造函數發生。

class A 
{ 
public: 
    A(string v) 
    { 
     cout << v; 
    } 

    A(unsigned char v) 
    { 
     cout << static_cast<bool>(v); 
    } 
}; 

int main() 
{ 
    A("Hello"); // <- Call A(string) 
    A(false); // <- Call A(unsigned char) 
} 

這樣你就不需要總是提供給超載和std::string既不const char*使代碼膨脹在客戶端調用點構建std::string

我不認爲這樣做更好,但更簡單。

+0

我有同樣的問題,但我想知道爲什麼A(「你好」);不會給出警告,但const char * b =「Hello」; A(B);給出警告4800:強制值爲bool'true'或'false'? – 2017-02-09 11:10:50

+0

這也適用於我,對於新的'string_view'也非常有用。例如,請參閱[這裏](https://godbolt.org/g/1uCwR2)。 – Claudius 2018-02-08 09:51:42