【问题标题】:delete via a pointer to Derived, not Base通过指向 Derived 而不是 Base 的指针删除
【发布时间】:2013-03-31 01:23:49
【问题描述】:

我实现了一个基本的智能指针类。它适用于以下类型的代码。 (考虑 Base1 有一个公共构造函数)

Sptr<Base1> b(new Base1);
b->myFunc();
{
    Sptr<Base1> c = b;
    Sptr<Base1> d(b);
    Sptr<Base1> e;
    e = b;
}

但是在测试代码中它有一个受保护的构造函数(我需要它是这样的)。和代码

Sptr<Base1> sp(new Derived);

产生以下错误(注意 Derived):

Sptr.cpp: In instantiation of ‘my::Sptr<T>::~Sptr() [with T = Base1]’:
Sptr.cpp:254:39:   required from here
Sptr.cpp:205:9: error: ‘Base1::~Base1()’ is protected
Sptr.cpp:97:17: error: within this context

问题是我必须确保通过指向 Derived 的指针而不是 Base1 进行删除。我该怎么做?

这是类代码(剪裁以显示构造函数和析构函数以及类成员)

template <class T>
class Sptr {
private:
   T* obj; // The actual object pointed by
       RC* ref;// A reference object to keep track of count
public:
  //declarations


template <typename T>
Sptr<T>::Sptr():obj(NULL),ref(NULL) {
    //do something
    std::cout<<"()\n";
    ref = new RC();
    ref->AddRef();
}

template <typename T>
Sptr<T>::Sptr(const Sptr &a) : obj(a.obj),ref(a.ref) {
    //do something
    std::cout<<"const Sptr\n";
    ref->AddRef();
}

template <typename T>
Sptr<T>::~Sptr() {
    //do something
    if(ref->Release() == 0) {
        if(obj)
            delete obj;

        delete ref;
    }
}

template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) : obj(u),ref(NULL) {
    //do something
    ref = new RC();
    ref->AddRef();
}

template <typename T>
template <typename U> 
Sptr<T>::Sptr(const Sptr<U> &u) : obj(u.obj),ref(u.ref) {
    std::cout<<"const Sptr<U>\n";
    ref->AddRef();
}

编辑

析构函数不是虚拟的。这就是我必须解决的情况。下面是Base1Derived

class Base1 {
    protected:
        Base1() : derived_destructor_called(false) {
            printf("Base1::Base1()\n");
        }
    private:
        Base1(const Base1 &); // Disallow.
        Base1 &operator=(const Base1 &); // Disallow.
    protected:
        ~Base1() {
            printf("Base1::~Base1()\n");
            assert(derived_destructor_called);
        }
    protected:
        bool derived_destructor_called;
};

class Derived : public Base1 {
        friend void basic_tests_1();
    private:
        Derived() {}
        Derived(const Derived &); // Disallow.
        Derived &operator=(const Derived &); // Disallow.
    public:
        ~Derived() {
            printf("Derived::~Derived()\n");
            derived_destructor_called = true;
        }
        int value;
};

【问题讨论】:

  • 如果你的析构函数是虚拟的,这应该重要吗?
  • 析构函数不是虚拟的
  • 您应该了解std::unique_ptr 如何使用删除器解决此问题:stackoverflow.com/q/8274451/103167
  • 我相信我在my answer here 中回答了您之前的问题的方法...
  • @footy:你为什么使用具有多态类的虚拟析构函数?

标签: c++ templates pointers c++11 smart-pointers


【解决方案1】:

如果将构造函数设为模板,则可以检测在构造时传入的指针类型并将该信息保存在智能指针中(例如,在多态删除器对象中)。这就是(我相信)shared_ptr&lt;&gt; 是如何做到的。如果传入的指针类型没有可访问的析构函数,您可能还可以使用 SFINAE 产生编译器错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 2023-04-01
    • 2019-03-31
    • 1970-01-01
    • 2010-09-08
    • 2014-01-07
    相关资源
    最近更新 更多