2016-12-01 121 views
1

我有一个纯虚类InterfaceCRTP造成段错误

class Interface { 
    public: 
    virtual ~Interface() noexcept; 
    virtual void open()=0; 
    virtual void close()=0; 
    protected: 
    explicit Interface(const string params); 
    string params_; 
} 

我再有,我实现我的业务逻辑的抽象类:

template<typename T> 
class AbstractInterface : public Interface { 
    public: 
    void open() override; 
    void close() override; 
    void read_is_complete(const vector<byte_array>); 
    protected: 
    explicit AbstractInterface(const string params); 
    virtual ~AbstractInterface() noexcept; 
} 

再有就是该接口的实现,使用CRTP的多态性:

class SPInterface : public AbstractInterface<SPInterface> { 
    public: 
    explicit SPInterface(const string params); 
    virtual ~SPInterface() noexcept; 
    void open(); 
    void close(); 
    void read_is_complete(const vector<byte_array> data); 
} 

我有一个单元测试,我创建一个insta的SPInterface NCE:

unique_ptr<Interface> intf; 
intf.reset(new SPInterface("aaa")); 

让这个脱身的范围内调用析构函数AbstractInterface这反过来呼吁AbstractInterface close方法,然后将它出现segfaults上this

template<typename T> 
void AbstractInterface<T>::close() { 
    static_cast<T *>(this)->close(); 
    params_ = ""; 
} 

这是令人困惑,因为我已经创建了该类的一个实例。 LLDB似乎证实:

AbstractInterface<SPInterface>::close(this=<unavailable>) 
+2

尝试从基类的析构函数调用派生类的方法看起来是否安全? – skypjack

+1

我认为你有一个点:) – ruipacheco

回答

3

让这个脱身的范围内调用析构函数AbstractInterface这反过来呼吁AbstractInterface close方法,然后将它出现segfaults在此:

template<typename T> 
void AbstractInterface<T>::close() { 
    static_cast<T *>(this)->close(); 
    params_ = ""; 
} 

看来你试图从基类的析构函数中调用派生类的方法。
这根本不安全,段错误是可执行文件告诉你它不认可的方式。 :-)

即使CRTP允许您调用属于派生类的成员函数(让我说)活动对象,它不会改变对象被破坏的方式。
不要忘记,基地和成员被毁坏在完成其构造函数的相反顺序。