2016-04-28 76 views
0

典型的工廠設計模式要求基類聲明虛擬析構函數,但實際上可以使用shared_ptr來避免這種情況。不含虛擬析構函數的多態的C++ shared_ptr

#include <iostream> 
#include <memory> 
#include <cstdio> 

using namespace std; 

class Dog { 
    public: 
    ~Dog() { cout << "dog destroyed\n"; } 
}; 

class Yellowdog : public Dog { 
    public: 
    ~Yellowdog() { cout << "Yellow dog destroyed.\n"; } 
}; 

class DogFactory { 
    public: 
    static shared_ptr<Dog> createYellowdog() { 
    return shared_ptr<Yellowdog>(new Yellowdog()); 
    } 
}; 

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

    auto ptr = DogFactory::createYellowdog(); 
    cout << ptr.use_count() << endl; 

    return 0; 
} 

在這種情況下,輸出是yellowdog destroyed隨後dog destroyed。但爲什麼?爲什麼使用shared_ptr可以在~Dog之前省略虛擬關鍵字?

+2

由於用指針複製/傳輸的'Deleter'。 – Jarod42

+0

因爲'shared_ptr'很神奇。 :-S –

+1

更清楚的是,'Deleter'與delete(Yellowdog *)p;'類似。您將通過'return shared_ptr (new Yellowdog())獲得UB;'儘管如此。 – Jarod42

回答

3

發生這種情況的原因是shared_ptr在控制塊中存儲了刪除類型的刪除程序,這是在創建第一個shared_ptr時創建的。在你的情況下,爲黃狗創建shared_ptr,刪除者是調用黃狗析構函數。

當您複製(或拷貝構造)一個shared_ptr到另一個,他們份額同一控制塊,以及新的共享PTR將會從原來的一個叫缺失者 - 一個將調用析構函數yellowdog。

但是,它並沒有真正使類具有多態性,並且不適合工廠實現 - 類中的任何其他非虛函數都將基於靜態類型shared_ptr進行調用,並且您不希望在多態類中使用該函數。