1

I'm writing some Arduino code and attempting to use inheritance in some classes. I have a class "Actor" (my base class) and a class "Marble" (which inherits from Actor). Here are the header files:

Actor.h:

#ifndef Actor_h
#define Actor_h

#include "Arduino.h"

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

Marble.h:

#ifndef Marble_h
#define Marble_h

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

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

Actor.cpp:

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

Actor::Actor()
{
}

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

Marble.cpp:

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

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

And finally, in the loop function I do:

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

  children[0].speak();

Which results in "Actor" being printed.

I discovered this nice link which seems similar to my issue, but the resolution does not seem to work for me: http://arduino.cc/forum/index.php?topic=41884.0

So. It seems like when I create my array of "Actors" and try and stick Marble in there it gets cast to an Actor, or something like that. Problem is, I'll have a few different characters that will all inherit from "Actor" and I'd like an array of them to iterate over and call overridden methods on them.

So, perhaps the problem is how I'm approaching this problem, or maybe there's some syntax errors? I don't know!

Thanks for your help, Kevin

2
  • 1
    shouldn't the speak method in Actor be marked as virtual also? Commented Feb 14, 2013 at 20:10
  • There are two errors here, Philip has pointed out the missing virtual and Steven has pointed out the fact that you are copying objects instead of referring to them though pointers. You have to fix both to get this working. Commented Feb 14, 2013 at 21:37

2 Answers 2

3

You need to declare speak as virtual in the Actor class, not just in the Marble class; without that, Actor::speak is a non-virtual function, so you will always be called in preference to the virtual Marble::speak.

For what it's worth, this has nothing to do with the Arduino: it's just a straight C++ issue.

Sign up to request clarification or add additional context in comments.

6 Comments

That's not correct. In this case that Marble::speak is virtual because it derives from a class that declares it virtual. It also won't fix the problem for reasons I am putting in an answer.
You're half right in that the code as written won't compile - you can't do children[0] = marble as they're of different types. However, changing all that over to pointers still doesn't fix the problem: Actor::speak still isn't virtual.
Try it yourself. When you declare a method that shares a signature with a virtual method in a parent class, it is itself virtual even if the keyword isn't present.
You've got the inheritance the wrong way round - the virtual declaration is in the derived class (Marble), not the base class (Actor); there is no "virtual method in a parent class" in this case.
@StevenBurnap Did you delete your answer? It was right, you need pointers for polymorphism to work.
|
1

Your problem is that children is an array of type Actor. The line children[0] = marble is taking a Marble object, converting it to an Actor object and copying the results to children[0]. Since the call to children[0].speak() is on an Actor, you get the Actor version.

In order for this to work the way you want, you need to copy a pointer or reference to the object rather than the object itself. That is, you want something like `Actor* children[2]':

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

children[0]->speak();

Of course if children has scope outside of loop, this will fail utterly and you'll need to use new to create your marbles.

Better yet, assuming Arduino has the STL, you should use vector and shared_ptr or something similar.

[Update] As Philip notes, this will also require that the speak method in Actor be declared virtual.

1 Comment

As above, this is wrong. children[0]->speak() will call the non-virtual Actor::speak. You really do need Actor::speak to be declared virtual for this to work. Try the code in this pastebin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.