我有这个基类:
// 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
构造函数调用它,该函数运行正常。
答案 0 :(得分:2)
您正在对WakeUp
对象进行切片。
您基本上拥有以下内容:
Gadget g = WakeUp(...);
此代码的作用如下:
WakeUp
对象。Gadget(const Gadget& other)
对象的基础调用WakeUp
。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.
使用指针会正确保留Gadget
和WakeUp
个实例,而不是将它们切片。
使用智能指针:
std::shared_ptr<Gadget> gadgets[1] = { std::make_shared<WakeUp>(&u8g) };