2013-05-27 55 views
0

我剛剛意識到我的代碼庫有點不一致,有些對象是使用構造函數A(const std::string&)從字符串構造而來的,還有一些是使用boost::lexical_cast<A>(const std::string&)從字符串構造的。構造函數從字符串VS詞法轉換爲字符串?

在我的理解中,這些符合相同的需求,但在許多方面表現不盡相同,格式錯誤的字符串的例外情況和轉換是我首先想到的,但我相信也有其他含義。所以我的問題是:我應該使用什麼,爲什麼?


編輯:按@ hetepeperfan的評論,我在改造常量的std :: string &,這是我首先意味着

+0

我認爲你的構造函數一般也應該使用const std :: string,除非你的構造函數真的需要改變字符串。 – hetepeperfan

+0

'boost :: lexical_cast (U)'如果'U'有輸出運算符並且'T'有輸入運算符''可以將'U'轉換爲'T' ...但是你的c'tor取決於它是如何實現的。 – ForEveR

+0

@hetepeperfan對,我只是改變了它。 –

回答

2

我可以想像的的std :: string參數類InputFile(類似於std::ifstream),其採用代表的路徑在文件系統中的文件中的字符串:

InputFile f("/dir/file.txt"); 
use(f); 

使用boost::lexical_cast這裏至少會有怪異。

我想這種觀察可以這樣推廣:如果您的類型A代表與std::string「可兼容」的值或可轉換爲std::string,則您有兩種選擇。但是,如果您在接口中公開一個構造函數,該構造函數將std::string類型的一個非可選參數用於其他目的而不是轉換值,則只有使用構造函數纔有意義(並且此構造函數應該可能爲explicit)。

+0

好點,我或多或少地想着一個消息的序列化字段,你可以隨時去兩個方向。 –

1

在我的理解,這些實現同樣需要[...]

他們不履行同樣需要。用於創建對象的接口應該總是最好地表達創建對象後面的語義。詞法轉換是將字符串值轉換(重新解釋)爲對象實例。如果你的對象是用一個字符串值構造而不是字符串中的值,使用boost :: lexical_cast只會令人困惑。

[...]但是在許多方面表現不盡相同,格式錯誤的字符串的例外情況和轉換是我心目中的第一個例外,但我相信也有其他含義。所以我的問題是:我應該使用什麼,爲什麼?

如果你的對象可以從任何字符串值構造(即不依賴於字符串中的值,但只是複製內部字符串),那麼你應該直接把它傳遞給構造函數。

如果字符串值傳遞給構造意味着你可以使用無效值創建一個實例,您應該使用工廠函數(即拋出一個錯誤之前實例化對象)或[更少首選]添加異常驗證在構造函數中(不理想,不太乾淨,在大多數情況下更糟糕的設計)。

如果你的對象實例模型,可以從值的字符串中的解釋(一「投」)來創建一個值/類型的專業化,那麼你應該支持通過boost::lexical_cast<YourClass>(const std::string&)創建它。

編輯:如果你構建一個對象與名稱(例如一些記錄器對象),但記錄儀的功能/價值並不取決於名字是什麼(對象記錄相同,只是用不同的名字),那麼你不應該定義一個基於lexical_cast的實現(因爲這個名字不會改變記錄器的功能)。

如果您創建的值/功能對象取決於字符串中的值(解析字符串中的值並將其轉換爲「複數」類實例),那麼實例的行爲取決於字符串中的內容(lexical_cast<ComplexNo>("(0 + 0i)")將返回不能被分割的內容,而不是lexical_cast<ComplexNo>("(1 + 0i)"))。在這種情況下(值對象取決於字符串中的內容)應該支持lexical_cast

基本上,爲值對象提供基於lexical_cast的實現。

+0

對不起,我不理解你的句子:「如果你的對象是用字符串值而不是字符串中的值構造的,那麼使用boost :: lexical_cast就會令人困惑。」你能提供一個例子嗎? –

+0

是:請參閱編輯我的文章。 – utnapistim

+0

好吧我現在明白了。看起來像Andrzej的答案一樣。 –

相關問題