nedak96
nedak96

Reputation: 5

Deleting an object with a protected destructor in another class

I know this question was asked before here: Delete an object with a protected destructor. But, the solution didn't work for me. I still get errors during compilation.

My project is also to create a smart pointer, and some of the tests have me deleting objects with protected destructors (some are virtual and some are not), which results in a compile-time error.

I really don't know where to start with fixing this issue. Thank you in advance!

This is the idea of what I have to do:

#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;
}

This code results in this error:

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(){

Upvotes: 0

Views: 1587

Answers (1)

Jarod42
Jarod42

Reputation: 217275

The thing is that your constructor take real type which can be destroyed, even if base class destructor is protected, something like:

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>;
    }
// ...
};

then, with:

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

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

You may do

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

Upvotes: 2

Related Questions