跳轉到內容

更多 C++ 習慣用法/物件生成器

來自 Wikibooks,開放書籍,開放世界

物件生成器

[編輯 | 編輯原始碼]

簡化物件建立,無需顯式指定型別。(這不是工廠方法模式)

也稱為

[編輯 | 編輯原始碼]

在 C++ 模板程式設計中,即使在小型程式中,物件的型別也會變得非常龐大且難以理解。例如,以下型別(Wrapper)是一個標準的一元函式物件,它封裝了類File中的成員函式read_line

struct File
{
  int read_line (std::string);
};
typedef std::mem_fun1_t<int, File, std::string> Wrapper;

使用for_each STL 演算法讀取一組檔案,在沒有物件生成器的情況下,看起來像這樣

void read_lines(std::vector<File *> files)
{
   typedef std::mem_fun1_t<int, File, std::string> Wrapper;  
   std::string arg;
   for_each(files.begin(), files.end(),
      std::binder2nd<Wrapper>(Wrapper(&File::read_line), arg));
}

上面的程式碼幾乎不可讀,並且比必要的多餘。即使型別定義也不能提高可讀性,因為Wrapper之類的佔位符型別定義會分散注意力。物件生成器習慣用法可以緩解這種情況。

解決方案和示例程式碼

[編輯 | 編輯原始碼]

物件生成器習慣用法中,會建立一個模板函式,它的唯一作用是從其引數構造一個新物件。它基於函式模板的一個有用屬性,而類模板沒有:函式模板的型別引數會從其實際引數自動推斷出來。例如,考慮 STL 中定義的一個簡單的物件生成器:make_pair

template <class T, class U>
std::pair <T, U> 
make_pair(T t, U u)
{
  return std::pair <T, U> (t,u);
}

make_pair 返回pair 模板的一個例項,具體取決於make_pair 函式的實際引數。例如,make_pair(1, 1.0) 透過自動推斷傳遞給物件生成器函式的物件型別,建立一個型別為:std::pair<int, double> 的物件。make_pair 在生成的 pair 物件不需要儲存在區域性變數的情況下特別有用。

map <int, double> m;
m.insert (make_pair(1,1.0)); // No need to know how pair template is instantiated.

C++ 標準庫定義了幾個物件生成器,以避免程式碼膨脹。std::bind2ndstd::mem_fun 是兩個這樣的標準物件生成器,可用於避免在上面動機部分所示的示例中程式碼膨脹。

void read_lines(std::vector<File *> files)
{
   std::string arg;
   for_each(files.begin(), files.end(), bind2nd(mem_fun(&File::read_line), arg));
}

已知用途

[編輯 | 編輯原始碼]

C++ 標準庫 (mem_fun、make_pair、bind1st、bind2nd 等)

[編輯 | 編輯原始碼]

型別生成器

物件生成器

華夏公益教科書