我有一个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
执行此操作时,我得到一个SIGABRT因为它试图执行virtual void fill() = 0;
答案 0 :(得分:7)
您无法从构造函数中调用纯虚函数。在构造函数运行时,该对象被认为是正在构造的类型,而不是任何派生类型。这意味着虚拟调度在正在构造的类型中“停止”。
这意味着从fill()
的构造函数调用a
将尝试调用a::fill()
,无论此a
子对象可以属于哪个派生类。这当然失败了,因为函数没有实现。
此外,正如@KerrekSB指出的那样,您的类需要一个虚拟析构函数。否则,如果delete
b
实例通过指向a
的指针{(很可能在涉及shared_ptr<a>
时),您将得到未定义的行为。
UPDATE 显然,shared_ptr
能够使用默认的删除器属性来解决虚拟析构函数的必要性,因此您的类在技术上可以没有。但是,如果没有虚拟析构函数,那么您的课程取决于仅在std::shared_ptr
中进行管理;如果你改变了那一点设计,你就会遇到麻烦(而且不会立即显而易见)。因此,我建议有一个虚拟的析构函数。
答案 1 :(得分:1)
"Never Call Virtual Functions during Construction or Destruction"
您可以使用std::make_shared
:
shared_ptr<a> sptr = std::make_shared<b>();
答案 2 :(得分:0)
您不应该从构造函数调用虚函数。读这个: https://stackoverflow.com/a/962148/1380817