2016-09-20 38 views
7

在下面的示例中,我的輸出爲「single param ctor」,兩次。 我的問題是雙重的,第一,爲什麼調用bool ctor而不是包含字符串的版本,第二,有沒有辦法在不調用調用的情況下調用字符串版本?錯誤類型的顯式構造函數

順便說一句,我實際的代碼不硬編碼字符串但像調用構造函數:

static constexpr auto NONE = "NONE"; 
Foo aFoo(NONE); 

...

#include <iostream> 
#include <string> 

using namespace std; 


struct Foo { 

    explicit Foo(bool _isVisible = false): id(""), isVisible(_isVisible) {cout << "single param ctor" << endl;} 
    explicit Foo(const string _id, bool _isVisible = false): id(_id), isVisible(_isVisible) {cout << "multip param ctor" << endl;} 

    const string id; 
    bool isVisible; 
}; 

int main(int argc, const char * argv[]) { 

    shared_ptr<Foo> sharedFoo = make_shared<Foo>("hello"); 
    Foo regFoo("hi"); 
    return 0; 
} 

回答

8

這是C的限制++從較早的C++繼承而來,最終從C.

您的字符串文字轉換爲bool的效果優於「用戶定義的」類型std::string

而是在通話鑄造的,你可以添加一個構造函數const char*,可能有它委託給現有的構造函數std::string

explicit Foo(const char* _id, bool _isVisible = false) 
    : Foo(std::string(_id), _isVisible) 
{}; 

此構造將是一個「精確匹配」(或無論如何足夠接近),並防止bool竊取風頭。或者,自C++ 14以來,而不是使用the std::string literal,例如, "hi"s,儘管你必須記得在一個通用的解決方案有點「meh」的callsite上做這件事。

順便說一下,如果你真的想拿你的std::string _id參數的價值,不要使它const;您正在阻止其從成員初始程序中移出並且需要副本。根據什麼在典型的調用點是怎麼回事,下面可能更有意義:

explicit Foo(
    string _id, 
    bool _isVisible = false 
) 
    : id(std::move(_id)) 
    , isVisible(_isVisible) 
{} 

如果平時在左值傳遞,不過,至少接受const std::string&,以防止一個副本。

+0

如若不是這個歪廢話隱*字符串字面*到*具有更高優先級的布爾*轉換在C++中被棄用? – WhiZTiM

+0

@WhiZTiM:在某些情況下引入'nullptr'是爲了提供幫助,但除非我們改變字符串文字的類型,或者刪除數組名稱 - 衰減,或者改變指針的工作方式,否則我們會被卡住。所以''foo's'然後引入給我們​​字符串文字,不會屈服於這個問題..但是這隻在你已經意識到這個問題時纔有用!如果你是,那麼它在源頭上相對容易解決(如上所示)。 –

+0

@WhiZTiM:順便提一句,您正在尋找的詞是「已棄用」。 –

0

爲什麼稱爲布爾構造函數而不是包含版本字符串

由於"hi" 字符指針 字符的陣列被轉換爲字符指針(感謝,亮度賽事在軌道),所以一個數字,我轉換爲布爾。

有沒有一種方法來獲取調用的字符串版本,而無需投入呼叫?

不是真的優雅,但......你可以通過第二個布爾PARAM

Foo regFoo("hi", false); 

排除第一個構造函數

+1

'「嗨」'是一個char數組,但表達式的類型會很快衰減到指向char的指針 –

+0

@LightnessRacesinOrbit - thanks;更正 – max66

+0

或使它成爲一個真正的std ::字符串文字在C++ 14中: 'Foo regFoo(「hi」s);' –