【问题标题】:Inheritance in Arduino CodeArduino 代码中的继承
【发布时间】:2013-02-14 20:07:05
【问题描述】:

我正在编写一些 Arduino 代码并尝试在某些类中使用继承。我有一个类“Actor”(我的基类)和一个类“Marble”(继承自 Actor)。以下是头文件:

演员.h:

#ifndef Actor_h
#define Actor_h

#include "Arduino.h"

class Actor
{
  public:
    Actor();
    void speak();
  private:
};
#endif

大理石.h:

#ifndef Marble_h
#define Marble_h

#include "Arduino.h"
#include "Actor.h"

class Marble : public Actor {
  public:
    Marble();
    virtual void speak();    
  private:
};
#endif

演员.cpp:

#include "Arduino.h"
#include "Actor.h"

Actor::Actor()
{
}

void Actor::speak() {
  Serial.println("Actor"); 
}

大理石.cpp:

#include "Arduino.h"
#include "Marble.h"

void Marble::speak() {
  Serial.println("Marble"); 
}

最后,在我做的循环函数中:

void loop() {
  Marble marble;
  Actor children[2];
  children[0] = marble;

  children[0].speak();

这会导致“演员”被打印出来。

我发现这个不错的链接似乎与我的问题相似,但该解决方案似乎对我不起作用: http://arduino.cc/forum/index.php?topic=41884.0

所以。似乎当我创建我的“演员”数组并尝试将 Marble 粘贴在其中时,它会被投射到演员或类似的东西上。问题是,我将有几个不同的字符,它们都将继承自“Actor”,我想要一个数组来迭代并在它们上调用覆盖的方法。

那么,也许问题在于我是如何处理这个问题的,或者可能存在一些语法错误?我不知道!

感谢您的帮助, 凯文

【问题讨论】:

  • Actor中的speak方法不应该也标记为virtual吗?
  • 这里有两个错误,Philip 指出了缺少的virtual,Steven 指出了您正在复制对象而不是通过指针引用它们的事实。您必须同时修复这两个问题才能使其正常工作。

标签: c++ inheritance arduino


【解决方案1】:

您需要在Actor 类中将speak 声明为virtual,而不仅仅是在Marble 类中;否则,Actor::speak 是一个 虚拟函数,因此您将始终优先于虚拟 Marble::speak 被调用。

对于它的价值,这与 Arduino 无关:这只是一个直接的 C++ 问题。

【讨论】:

  • 这不正确。在这种情况下,Marble::speak 是虚拟的,因为它派生自一个声明它为虚拟的类。由于我要回答的原因,它也无法解决问题。
  • 你说对了一半,因为编写的代码无法编译 - 你不能这样做 children[0] = marble 因为它们是不同的类型。但是,将所有内容更改为指针仍然不能解决问题:Actor::speak 仍然不是虚拟的。
  • 自己试试吧。当您声明与父类中的虚拟方法共享签名的方法时,即使关键字不存在,它本身也是虚拟的。
  • 你把继承弄错了——虚拟声明在派生类(Marble)中,而不是基类(Actor)中;在这种情况下,没有“父类中的虚拟方法”。
  • @StevenBurnap 你删除了你的答案吗?没错,你需要多态性的指针才能工作。
【解决方案2】:

您的问题是childrenActor 类型的数组。 children[0] = marble 行采用Marble 对象,将其转换为Actor 对象并将结果复制到children[0]。由于对children[0].speak() 的调用是在Actor 上进行的,因此您将获得Actor 版本。

为了让它按照你想要的方式工作,你需要复制一个指向对象的指针或引用,而不是对象本身。也就是说,你想要像 `Actor* children[2]' 这样的东西:

Marble marble;
Actor* children[2];
children[0] = &marble;

children[0]->speak();

当然,如果children 的范围超出loop,这将完全失败,您需要使用new 来创建弹珠。

更好的是,假设 Arduino 具有 STL,您应该使用 vectorshared_ptr 或类似的东西。

[更新] 正如 Philip 所说,这还需要将 Actor 中的 speak 方法声明为虚拟的。

【讨论】:

  • 如上,这是错误的。 children[0]->speak() 将调用 非虚拟 Actor::speak。您确实需要将 Actor::speak 声明为 virtual 才能使其正常工作。试试this pastebin中的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多