基函数和派生虚函数都没有被正确调用

Nor base nor derived virtual function being properly called

我有这个基地class:

// put the display in a macro on a .h file for less headache.
class Gadget {
  protected:
    int x, y;
    U8GLIB * u8g;

    virtual int  f_focus()  {return 0;};
    virtual int  f_blur()   {return 0;};
    virtual void f_draw()   {};
    virtual void f_select() {};


  public:
    Gadget(U8GLIB * u8g, int x, int y) :
      u8g(u8g),
      x(x),
      y(y)
    {
      Serial.println(F("Gadget(U8GLIB * u8g, int x, int y)"));
    };

    Gadget() {
      Serial.println(F("Gadget()"));
    };

    int     focus(){return f_focus();};
    int     blur(){return f_blur();};
    void    draw(){f_draw();};
    void    operator()(){f_select();};
};

而这个派生class:

class WakeUp :
  public Gadget
{
  public:
    WakeUp(U8GLIB * u8g) :
      Gadget(u8g, 0, 0)
    {
      Serial.println(F("WakeUp(U8GLIB * u8g)"));
    };

};

然后我在数组中实例化唤醒 class,如下所示:

Gadget gadgets[1] = {
  WakeUp(&u8g)
};

然后我尝试像这样访问这个成员:

void focus() {
  Serial.println(gadgets[0].focus());
}  

应该显示0。但是它显示 -64。即使我覆盖 WakeUp class 上的 f_focus() 方法。如果我从 f_focus() 中删除 virtual 说明符,它工作正常,显示 0,但我将无法访问此方法的派生 class 实现。 我想了解是什么导致了这种奇怪的行为,我该怎么做才能避免这种情况。

编辑:

如果我从 Gadget 构造函数中调用该函数,该函数运行良好。

您正在切割 WakeUp 对象。

你基本上有以下内容:

Gadget g = WakeUp(...);

这段代码的作用如下:

  1. 构造一个WakeUp对象。
  2. 使用 WakeUp 对象的基础调用 Gadget(const Gadget& other)
  3. 销毁临时WakeUp对象,只留下Gadget基础的副本。

为了避免这种情况,需要创建一个指针数组(如果是智能指针就更好了)。

Gadget* gadgets[1] = { new WakeUp(&u8g) }; // If you choose this method, you need to call 
                                           // delete gadget[0] or you will leak memory.

使用指针将正确保留 GadgetWakeUp 实例,而不是将它们切片。

使用智能指针:

std::shared_ptr<Gadget> gadgets[1] = { std::make_shared<WakeUp>(&u8g) };