为什么没有调用子类的虚函数

时间:2016-01-08 16:06:46

标签: c++ arduino

我有一个基础和一个派生类:

plugin.h

#ifndef PLUGIN_H
#define PLUGIN_H

// plugin states
#define PLUGIN_IDLE 0

class Plugin {
public:
  Plugin();
  ~Plugin();

  virtual void loop();
};

#endif

plugin.cpp

#include <Arduino.h>
#include "plugin.h"

Plugin::Plugin() {
}

Plugin::~Plugin(){
}

void Plugin::loop(){
  Serial.println("Plugin::loop()");
}

派生类

class OneWirePlugin : public Plugin {
public:
  OneWirePlugin(byte pin);
  void loop();
};

OneWirePlugin::OneWirePlugin(byte pin) {
}

void OneWirePlugin::loop() {
  Serial.println("OneWirePlugin::loop()");
}

我原以为调用派生实例的loop()方法会执行OneWirePlugin::loop()

但是,当我在派生类上下文中调用它时,只发生

Plugin p = Plugin();
Plugin o = OneWirePlugin(ONEWIRE_PIN);
OneWirePlugin q = OneWirePlugin(ONEWIRE_PIN);
p.loop(); // Plugin::loop()
o.loop(); // Plugin::loop()
q.loop(); // OneWirePlugin::loop()

允许调用派生实现的虚拟方法有什么问题,特别是在通过*Plugin指针引用时?

2 个答案:

答案 0 :(得分:7)

loop必须声明为virtual

class Plugin {

// ...

virtual void loop();

此外,要使多态性起作用,您需要一个指针或引用:

Plugin* o = new OneWirePlugin(ONEWIRE_PIN);
o->loop();

// ...

delete o;

(在您的代码中,slicing出现,如评论部分中的Mat所示)

然后,考虑使用智能指针(如unique_ptrshared_ptr)。

如果你正在使用C ++ 11,你还应该在子类中使用loop说明符标记override

class OneWirePlugin : public Plugin {

// ...

void loop() override { 

答案 1 :(得分:0)

在你的问题中 - 1.插件p = new Plugin(); 2.插件o = OneWirePlugin(ONEWIRE_PIN);

  1. 将调用Plugin :: loop()作为基类对象。
  2. 当你创建Plugin对象时,
  3. 也会调用Plugin :: loop(),这样就会发生对象切片,从派生类对象中形成基类对象。
  4. 以下示例将有所帮助。

    class Base { int x, y; };
    
    class Derived : public Base { int z, w; };
    
    int main() 
    {
        Derived d;
        Base b = d; // Object Slicing,  z and w of d are sliced off
    }
    

    在IDE上运行 将派生类对象分配给基类对象时会发生对象切片,派生类对象的其他属性会被切除以形成基类对象。