2016-04-28 98 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进行调用,并且您不希望在多态类中使用该函数。