【问题标题】:Deleting an object with a protected destructor in another class删除另一个类中带有受保护析构函数的对象
【发布时间】:2017-04-21 18:35:41
【问题描述】:

我知道之前有人问过这个问题:Delete an object with a protected destructor。但是,该解决方案对我不起作用。我在编译过程中仍然会出错。

我的项目也是创建智能指针,有些测试让我删除了带有受保护析构函数的对象(有些是虚拟的,有些不是),这会导致编译时错误。

我真的不知道从哪里开始解决这个问题。提前谢谢!

这是我必须做的想法:

#include <cstddef>

template<typename T> void DefaultDeleter(void *p) { delete static_cast<T*>(p); }

struct ref_counter {
    int refs;
    void *p;
    void (*d)(void *);
};

template<typename T> class Sptr { 
    public:
            Sptr(T *obj){
            c = new ref_counter;
            c->refs = 1;
            c->p = static_cast<void*>(obj);
            c->d = &DefaultDeleter<T>;
            p = p;
        }
        void reset(){
            (c->d)(c->p);
            delete c;
        }
    private:
        T *p;
        ref_counter *c;
};

class Base{
    public:
        Base(){
            atr = new int(1);
        }
    protected:
        ~Base(){
            delete atr;
        }
    private:
        int *atr;
};

int main(){
    Base b1;
    Sptr<Base> s1(&b1);
    return 0;
}

此代码导致此错误:

root@resnet-230-99:~/cs440/a3# g++ test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:43:7: error: ‘Base::~Base()’ is protected within this context
  Base b1;
       ^~
test.cpp:35:3: note: declared protected here
   ~Base(){
   ^
test.cpp: In instantiation of ‘void DefaultDeleter(void*) [with T = Base]’:
test.cpp:17:9:   required from ‘Sptr<T>::Sptr(T*) [with T = Base]’
test.cpp:44:19:   required from here
test.cpp:3:53: error: ‘Base::~Base()’ is protected within this context
 template<typename T> void DefaultDeleter(void *p) { delete static_cast<T*>(p); }
                                                     ^~~~~~
test.cpp:35:3: note: declared protected here
   ~Base(){

【问题讨论】:

  • 嗯,是的,~Base() 无法从 DefaultDeleter 访问。也许如果你有一个带有公共析构函数的 Derived 类和一个 Derived* 指针,你可以做点什么。
  • 您从接受的答案中遗漏了一个非常重要的注释:我当然假设Base 的析构函数是protectedDerived 的析构函数是public,如否则这个练习毫无意义。
  • 不管怎样,Sptr&lt;Base&gt; s1(&amp;b1) 对智能指针毫无意义,你会自动取消分配应该分配的东西。
  • [OT]:您的重置功能在共享所有权的上下文中是错误的(您不使用参考计数器)。
  • p = p; 也很可疑。

标签: c++ protected


【解决方案1】:

问题是您的构造函数采用可以销毁的真实类型,即使基类析构函数受到保护,例如:

template<typename T>
class Sptr {
public:
    template <typename U>
    explicit Sptr(U* obj){
        c = new ref_counter;
        c->refs = 1;
        c->p = static_cast<void*>(obj);
        c->d = &DefaultDeleter<U>;
    }
// ...
};

然后,用:

class Base {
protected:
    ~Base() = default;
};

class Derived : public Base
{
public:
    ~Derived() = default;
};

你可以这样做

Sptr<Base> p{new Derived()};

【讨论】:

  • 你是对的!这正是测试用例试图做的事情。非常感谢您的帮助!
猜你喜欢
  • 2012-02-05
  • 2019-11-24
  • 2013-05-18
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 2013-11-03
  • 1970-01-01
  • 2020-03-06
相关资源
最近更新 更多