我有一个abstact基类,在它的构造函数中调用一个虚方法.在传递一个shared_ptr基类之后,找不到该方法的实现.
class a
{
public:
a() { fill(); }
protected:
virtual void fill() = 0;
}
class b : public a
{
public:
b() : a();
protected:
virtual void fill() { // do something }
}
....
shared_ptr<a> sptr = shared_ptr<a> ( new b()): // error happens here on runtime
Run Code Online (Sandbox Code Playgroud)
执行此操作时,我得到一个SIGABRT,因为它试图执行 virtual void fill() = 0;
您无法从构造函数中调用纯虚函数.在构造函数运行时,该对象被认为是正在构造的类型,而不是任何派生类型.这意味着虚拟调度在正在构造的类型上"停止".
这意味着fill()从构造函数调用a将尝试调用a::fill(),无论该a子对象可以属于哪个派生类.这当然失败了,因为该功能没有实现.
另外,正如@KerrekSB指出的那样,你的类需要一个虚拟析构函数.否则,你会得到未定义的行为,如果你曾经delete一个b通过指针实例a(这是很可能的时候shared_ptr<a>参与).
更新显然,shared_ptr能够使用默认的删除器属性来解决虚拟析构函数的必要性,因此您的类在技术上可以没有.但是,如果没有虚拟析构函数,您的类依赖于std::shared_ptr仅在s中进行管理; 如果你改变了那一点设计,你就会遇到麻烦(而且不会立即显而易见).因此,无论如何,我建议使用虚拟析构函数.