CRTP导致段错误

时间:2016-12-01 20:47:02

标签: c++ c++11 polymorphism crtp pure-virtual

我有一个纯虚拟课程Interface

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

我有一个单元测试,我在其中创建SPInterface的实例:

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

让这个超出范围会调用析构函数AbstractInterface,它会在AbstractInterface上调用close方法,然后在this上调用segfaults:

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

由于我已经创建了该类的实例,因此令人困惑。 lldb似乎证实:

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

1 个答案:

答案 0 :(得分:3)

  

让这个超出范围调用析构函数AbstractInterface,它反过来调用AbstractInterface上的close方法,然后对此进行段错误:

public void updateList(){
   // fragment has a ListView - listview
   // and an Adapter for the list - adapter
   // add, remove, move, items in adapter
   // and call notifyDataSetChanged();
   adapter.notifyDataSetChanged();
}

您似乎正在尝试从基类的析构函数中调用派生类的方法。
这根本不安全, segfault 是可执行文件告诉您它不同意的方式。 : - )

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