Reputation: 5
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
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