也没有正确调用基础或派生的虚函数

时间:2017-09-18 14:47:27

标签: arduino arduino-c++

我有这个基类:

// 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 WakeUp :
  public Gadget
{
  public:
    WakeUp(U8GLIB * u8g) :
      Gadget(u8g, 0, 0)
    {
      Serial.println(F("WakeUp(U8GLIB * u8g)"));
    };

};

然后我在这样的数组中实例化WakeUp类:

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

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

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

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

修改

如果我从Gadget构造函数调用它,该函数运行正常。

1 个答案:

答案 0 :(得分:2)

您正在对WakeUp对象进行切片。

您基本上拥有以下内容:

Gadget g = WakeUp(...);

此代码的作用如下:

  1. 构建WakeUp对象。
  2. 使用Gadget(const Gadget& other)对象的基础调用WakeUp
  3. 销毁临时WakeUp对象,只保留Gadget库的副本。
  4. 为了避免这种情况,你需要创建一个指针数组(如果它们是智能指针,那就更好了。)

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