C ++:运算符delete(void *)受保护

时间:2019-01-07 12:52:32

标签: c++

我正在学习C ++ 11,并使用以下代码得到此错误消息:

test.cpp:11:13: error: ‘static void Base::operator delete(void*)’ is protected
 inline void Base::operator delete(void* p){
             ^
test.cpp:32:45: error: within this context
     std::unique_ptr<Derived, Deleter> p(new Derived);

问题:为什么我会收到此错误?我应该如何解决? 我认为受保护的成员也应该可由派生类中的成员函数访问。还是我错误地使用了unique_ptr?

test.cpp如下:

#include <memory>

class Base{
public:
    virtual void Release() const = 0;
protected:
    virtual ~Base() = default;
    static void operator delete(void* p);
};

inline void Base::operator delete(void* p){
    ::operator delete(p);
};

struct Deleter{
    constexpr Deleter() noexcept = default;
    void operator()(const Base* ptr) const{
        ptr->Release();
    }
};

class Derived : public Base{
public:
    void Release() const;  
};

void Derived::Release() const{
    delete this;
}

int main(){
    std::unique_ptr<Derived, Deleter> p(new Derived);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

You have protected the delete operator, therefore it is only accessible from within the class itself and it's subclasses. Simply make it public by adding public: before the declaration.

#include <memory>

class Base{
public:
    virtual void Release() const = 0;
protected:
    virtual ~Base() = default;
public:  // <----- ADD THIS HERE
    static void operator delete(void* p);
};

inline void Base::operator delete(void* p){
    ::operator delete(p);
};

struct Deleter{
    constexpr Deleter() noexcept = default;
    void operator()(const Base* ptr) const{
        ptr->Release();
    }
};

class Derived : public Base{
public:
    void Release() const;
};

void Derived::Release() const{
    delete this;
}

int main(){
    std::unique_ptr<Derived, Deleter> p(new Derived);
    return 0;
}

As the answers in the linked question say, deletemust be globally accessible. Unfortunately I can't find it in the standard, but here is a quote from cppreference, which I think is the one that applies here:

If the static type of the object that is being deleted differs from its dynamic type (such as when deleting a polymorphic object through a pointer to base), and if the destructor in the static type is virtual, the single object form of delete begins lookup of the deallocation function's name starting from the point of definition of the final overrider of its virtual destructor. Regardless of which deallocation function would be executed at run time, the statically visible version of operator delete must be accessible in order to compile. In other cases, when deleting an array through a pointer to base, or when deleting through pointer to base with non-virtual destructor, the behavior is undefined.