1

I am in the process of creating a scene graph for a 2D game engine. I've created a base class called Node, which is derived by Sprite, which in turn is derived by Player. Each class has the virtual function update(). I want to call every update() in each class. I don't know if this is possible (Except using base::update(), but that's a little messy with many derived classes).

The following code provides a little insight into the current structure of my project.

#include <iostream>

class Base
{
public:
    virtual void print()
    {
        std::cout << "Hello from Base ";
    }
};

class Derived : public Base
{
public:
    virtual void print()
    {
        std::cout << "and Derived!" << std::endl;
    }
};

int main()
{
    Derived foo = Derived();
    foo.print(); // Obviously outputs only "and Derived!"
}

While the above does exactly as expected, my desired output is actually "Hello from Base and Derived!".

I know I can put Base::print() at the top of Derived::print(), but I am looking for a method to that's a little cleaner with many derived classes on top of each other. I'm a little new to C++ as a language, and I couldn't find info on this subject. I'm open to complete changing my approach if it's not in the style of proper polymorphism. I'd rather do things right than botching it to just get this affect.

  • Is it okay if it works only with virtual dispatch and not static linkage? – Weak to Enuma Elish Aug 31 '19 at 23:19
  • 1
    It's a shame that C++ doesn't have objective-C's `super` keyword. That solves the problem at a stroke. – Paul Sanders Aug 31 '19 at 23:20
  • @WeaktoEnumaElish Shouldn't be a problem for me. – Ted Johnson Aug 31 '19 at 23:26
  • @PaulSanders I wish... It's quite difficult to traverse inheritance without explicitly stating your action, but I guess that's actually more inline with what C++ is. – Ted Johnson Aug 31 '19 at 23:26
  • Some suggestions [here](https://www.fluentcpp.com/2017/12/26/emulate-super-base/) and [here](https://stackoverflow.com/questions/180601/using-super-in-c) – Paul Sanders Aug 31 '19 at 23:35
  • If it helps, you can declare in Derived `typedef Base super;` to get the convenience of using an Objective-C like `super` to refer to the base class. Breaks down a bit for multiple inheritance. – Eljay Aug 31 '19 at 23:43
  • @Eljay The situation gets more complicated having more than a single derived interface implemented. That's true. – πάντα ῥεῖ Aug 31 '19 at 23:48

2 Answers2

2

I know I can put Base::print() at the top of Derived::print(), but I am looking for a method to that's a little cleaner with many derived classes on top of each other.

You have to do that explicitely if you want it, That's the whole point of overriding with polymorphism.

class Derived : public Base
{
public:
    virtual void print()
    {
        Base::print();
        std::cout << "and Derived!" << std::endl;
    }
};

As you're mentioning graphs (tree like structures), you should have a look at the Visitor Pattern.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Never forget that C++ is just C with some object orientation clumsily bolted on. – Mark Ransom Aug 31 '19 at 23:18
  • @MarkRansom I don't see how that would change with any other OOP programming language I am aware of. If there would be some automated call for base inherited I would be quite confused what's going on. With Delphi we have `inherit` which is shorter, but not inherently better. – πάντα ῥεῖ Aug 31 '19 at 23:20
  • 90% of my OO experience is with C++, and Python isn't much different so I'm not qualified to dispute your assertion. I do wonder how something like [Smalltalk](https://en.wikipedia.org/wiki/Smalltalk) would handle this though, since it was designed from the outset to be OO. – Mark Ransom Aug 31 '19 at 23:30
  • @Mark I think it would be in a similar way (`super`, `inherit` whatever). Any different behavior (i.e. opt out) won't make sense, or at least leave developers in heavy confusion. – πάντα ῥεῖ Aug 31 '19 at 23:35
0

Sometimes C++ does something you are not expecting.

My advice is to use a feature of the C language that it has to support.

In this case, I used union to achieve the programmatic effect you are seeking:

#include <iostream>

class Base
{
public:
    virtual void print()
    {
        std::cout << "Hello from Base ";
    }
};

class Derived : public Base
{
public:
    virtual void print()
    {
        std::cout << "and Derived!" << std::endl;
    }
};

int main(void);
int main()
{
    Base foo;
    Derived bar;
    union foobar {Base *b; Derived *d;} fb;

    fb.b = &foo; fb.b->print();
    fb.d = &bar; fb.d->print();

    return 0;
}

CODE LINK: http://ideone.com/JdU8T6

C. R. Ward
  • 93
  • 5