2017-04-21 66 views
0

我知道此問題之前在此處詢問過: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; 
} 

該代碼產生此錯誤:

[email protected]:~/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(){ 
+0

嗯,是的,'〜基地()'是不是從'DefaultDeleter'訪問。也許如果你有一個帶有公共析構函數和Derived *指針的Derived類,你可以做一些事情。 – aschepler

+0

您錯過了接受答案中的一個非常重要的註釋:*我當然假定'Base'的析構函數是'protected',而Derived''''是'public'',否則這個練習就沒有意義了。* –

+1

無論如何,'Sptr s1(&b1)'對智能指針沒有意義,您會自動釋放應該分配**的內容。 – Jarod42

回答

2

的事情是,你的構造需要可以摧毀真正的類型,即使基類的析構函數是受保護的,是這樣的:

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()}; 
+0

你是對的!這正是測試用例試圖做的。非常感謝你的幫助! – nedak96

相關問題