2013-06-04 84 views
2

我正在開發一個個人項目,以熟悉C++ 11和Boost。C++ 11智能指針的複合模式

我與UrlExtractor基類有一個繼承關係,TagUrlExtractor派生類和CompoundExtractor派生類。 A CompoundExtractor可以包含任意數量的UrlExtractors,從而實現composite pattern

我很好奇CompositeExtractor.addExtractor的方法簽名應該是什麼樣子。由於我正在處理多態類型,我不得不使用指針(或引用)。我想使用新的智能指針,特別是shared_ptr

我試着寫這樣的addExtractor成員函數:

void addExtractor(shared_ptr<UrlExtractor> extractor); 

不過,我得到一個編譯錯誤,如果我嘗試寫:

compound.addExtractor(new TagUrlExtractor()); 

的問題,將採取兩個隱含的轉換爲創建一個shared_ptr<UrlExtractor>:一個到UrlExtractor基類,第二個到shared_ptr

我可以調用該函數是這樣的:

compound.addExtractor(shared_ptr<UrlExtractor>(new TagUrlExtractor)); 

然而,這是非常冗長。這種情況如何正常處理?

回答

8

的問題是,它會採取兩種隱式轉換爲創建一個shared_ptr:一到UrlExtractor基類和第二到shared_ptr的

這不是問題:問題是,構造接受原始指針的shared_ptr被標記爲explicit,所以它不能在複製初始化上下文中使用(函數參數被複制初始化,如§8.5/15所指定)。

你可以(實際上,應該)使用std::make_shared

compound.addExtractor(std::make_shared<TagUrlExtractor>()); 

std::make_shared()有被異常安全執行一個動態分配的少,當你從一個new初始化共享指針比優勢表達(也參見this Q&A on StackOverflow)。

+0

這實際上消除了需要做一個明確的'新'。非常好! –

+2

@TravisParks:事實上,在C++ 11中,除非您正在進行真正的低級別內存管理(如編寫自己的容器等),否則幾乎不需要使用'new',而在C++ 14中,您可以刪除「幾乎」 - 感謝'std :: make_unique()';-) –

+1

@AndyProwl:我會爭辯說'new'仍然很常見,直到我們得到'make_unique'('unique_ptr'常常是最好的選擇) 。另一方面,「刪除」在C++ 11代碼中應該幾乎不存在(好信息)。 – Grizzly