2013-11-24 57 views
8

它已經比我上次使用C++的很長一段時間,從Java和Python回來了,我有一個基於C的良好做法++問題:C++包裝類型語義

我想保持一個語義代碼有關一些非常簡單的對象,比方說我們有對象標籤和文件,它們只是std :: string和一個包含使用標籤和文件的幾個函數的類TagManager。

我的問題是,是創建一個自定義類型代表這些微不足道的對象或直接使用它們是什麼?

更具體的我能有一個函數的定義之一:

TagIterable myFunction(Tag tag, File file); 
std::vector<Tag> myFunction(Tag tag, File file); 
std::vector<std::string> myFunction(std::string tag, std::string file); 

我傾向於第一種解決辦法,因爲我想保持一個語義代碼,在另一方面做起來需要用戶檢查這些類型是什麼,因此減少了使用的簡單性。

我還閱讀了另一個問題(Thou shalt not inherit from std::vector)'不要生產新的實體,只是爲了讓事情看起來更好。

那麼你在這種情況下做什麼, C++哲學推薦做什麼?

+1

文件代表一個實際的文件?或者這是否意味着它是一個文件名?那麼將其稱爲文件名會更好,因爲它可能會誤導其他人使用您的代碼... – xmoex

回答

5

我通常在這種情況下使用typedef S:

  • 即使typedef■不要引入新類型或std::vector<>討厭自己的衍生物,別名可能仍然是使用這些代碼可能是惱人的間接性。
  • 另一方面,他們可能會被暴露並記錄得很好(提供一個例子),以便每個人從開始就使用它們。
  • 如果需要更改類型(假設在特定情況下未使用特殊std::string功能或在替換中提供了這些功能),它們有助於避免構建斷路器。
  • 因此,如果需要,以後可以將typedef更改爲具有額外屬性和功能的新類別別名,或僅用於類型安全性。
  • 它們允許輕鬆跟蹤使用位置,以及在大多數IDE中進行重構。
namespace mylib 
{ 
    typedef std::string Tag; //perhaps 'TagType' or 'tag_type', to follow the naming 
          //conventions of the standard library, e.g. 
          //std::vector::value_type 
    typedef std::string File;//Same as above, 'FileName' might be more appropriate 

    typedef std::vector<Tag> TagIterable; 
          //Could be named 'TagContainer', 
          //`TagVector` or `TagSet` when using std::set, 
          //to match the terminology of C++ 

    TagIterable myFunction(const Tag& tag,const File& file); 
          //One may use references to const here, 
          //to explicitly avoid unnecessary copies 

}; 
2

它被稱爲encapsulation(也稱爲數據隱藏)。如果封裝FileTag的概念增加了價值,那就繼續做下去,否則您只會增加複雜性。稍後您可能會決定在類中內部使用std::wstring而不是簡單的std::string,如果您創建TagFile類,並且最有可能不會影響類的用戶,則可以輕鬆更改這些類。

至於從std :: vector繼承,這的確是你應該避免的東西。但請記住:繼承和封裝是兩個完全不同的概念。

1

我會preferr用什麼C++爲您提供,除非它是真的必要做出的別名。爲什麼不只是使用自稱識別器?我的解決辦法是這樣的:

std::vector<std::string> getTagsFromFile(std::string tag, std::string fileName); 
+0

總的來說,簡單總是更好。還有一點需要考慮的是,封裝它會使其具有面向未來的實施變化。 – Brady

0

有一些有效的使用情況進行包裝(簡單)類型:

  • Makeing類型不同。例如,對於某些上下文來說唯一的標識符。
  • 給出一個單位類型(美國加侖3.79與英制加侖4.546) - 例如boost :: unit。 單位實際上是附加信息。
  • ...

對於每一個包裹,你將創建不同的類(模板),以確保類型安全。 一個簡單的typedef不會封裝任何東西,但只是澄清用法。

1

作爲我的類型怪胎,我總是包含新類型。

編寫包裝代碼是很容易的:

class Tag { 
public: 
    Tag() {} 
    explicit Tag(std::string const& v): _value(v) {} 
    std::string const& get() const { return _value; } 
private: 
    std::string _value; 
}; // class Tag 

就是這樣!

typedef很好,但它很容易混淆,並使用無意義的操作:Tag::substr是什麼意思?