C ++切片和虚拟析构函数

时间:2018-06-16 11:49:12

标签: c++ slice virtual-destructor

我得到了一个原始指针的矢量,我将其复制。这些指针指向的对象的所有权属于某些其他模块。我必须用一些指向新创建的对象的指针替换一些指针。所以最后我会有一个带指针的向量,我需要调用delete和其他我不需要的指针。我的想法是引入新的类,使其自动化。

template <typename T, class = std::enable_if_t<std::is_pointer<T>::value>>
class Pointer {
public:
    Pointer(T p) : pointer_(p) {}
    virtual ~Pointer() = default;

    T operator->()  { return pointer_; }

protected:
    T pointer_;
};

template <typename T>
class NotOwnedPointer : public Pointer<T> {
public:
    NotOwnedPointer(T p) : Pointer<T>(p) {}
    ~NotOwnedPointer() { std::cout << "not owned\n"; }
};

template <typename T>
class OwnedPointer : public Pointer<T> {
public:
    OwnedPointer(T p) : Pointer<T>(p) {}
    ~OwnedPointer() { std::cout << "owned\n"; delete this->pointer_; this->pointer_ = nullptr; }
    OwnedPointer(const OwnedPointer&) = delete;
    OwnedPointer& operator=(const OwnedPointer& other) = delete;
};

struct Foo {
    int i;
};

int main() {
    Foo* foo = new Foo{42};
    std::vector<Pointer<Foo*>> v;
    v.push_back(NotOwnedPointer(foo));
    v.push_back(OwnedPointer(foo));
}

请注意,我使用Pointer作为矢量类型而不是Pointer*。这样,当我将派生类实例添加到向量时,就会发生切片。

当向量被破坏时将调用哪些析构函数?由于向量的类型是Pointer,我会说将使用类Pointer的虚拟表,并且将调用~Pointer(),但是当我运行程序时,它会打印来自~NotOwnedPointer()~OwnedPointer()

1 个答案:

答案 0 :(得分:1)

v.push_back(NotOwnedPointer(foo));
v.push_back(OwnedPointer(foo));

这两行创建临时对象(分别为NotOwnedPointerOwnedPointer类型),然后将其切片并复制到矢量中。

当销毁临时对象时,会分别调用它们的析构函数(~NotOwnedPointer()~OwnedPointer())。这与v无关,后来会被销毁。