-1

Suppose I have the class

class BaseClass {
  public:
    BaseClass();
    ~BaseClass();
    
    void runAllMethods();
};

and the sub class

class SubClass : public BaseClass {
  public:
    SubClass();
    ~SubClass();

    // arbitrary methods
    void method1();
    void method2();
    ...
};

Suppose I then create the object

SubClass myObject = SubClass();

How do I write runAllMethods() in BaseClass so that it can run all methods of itself, including the methods defined in SubClass (e.g. methods1(), method2(), etc.)? In other words, how do I get a superclass to access the methods in a subclass without knowing the names of the subclass' methods?

HarrisonO
  • 31
  • 6
  • 3
    You can't. C++ does not yet have the reflection capabilities you are used to from other languages. Either override `runAllMethods` in the subclass or collect "all methods" in another way (a `std::vector` of function pointers, for example). – Botje Jun 25 '20 at 07:58
  • 1
    Does [How can I add reflection to a C++ application?](https://stackoverflow.com/questions/41453/how-can-i-add-reflection-to-a-c-application) answer your question? – Ted Lyngmo Jun 25 '20 at 08:01
  • 1
    Show some [mre] in your question. What is your program doing? How many millions lines of C++ code do you already have? On what operating system and compiler? **Please [edit](https://stackoverflow.com/posts/62570435/edit) your question to improve it** – Basile Starynkevitch Jun 25 '20 at 08:42
  • Meta: Why would you run methods you know nothing of (parameters, return value, functionality)? Especially all of the methods? – Lorinczy Zsigmond Jun 26 '20 at 07:37

2 Answers2

1

How can I iterate through unknown object methods in C++?

As far as I know, this is impossible. Check by reading n3337 (the C++11 standard).

A possible approach is to generate the C++ code running all of them.

You could use some meta-programming approach (like Qt does with its moc, which generates C++ code), or you could use some preprocessor (e.g. GPP) driven by your build automation tool. GNU autoconf might be inspirational.

If you compile your C++ code with GCC, consider extending it with plugins.

You might consider some X-macro tricks.

If your operating system has plugins, you might generate them at runtime then load them. On Linux, see dlopen(3) and dlsym(3) and C++ dlopen mini howto and How to write shared libraries.

On some OSes, ou could use JIT compilation techniques to generate machine code at runtime, like GCC libgccjit enables you. Or use asmjit

Be aware of lambda expressions in C++11. Maybe they could be useful (in addition of other approaches).

Consider also coding in other programming languages (such as Common Lisp; it is homoiconic, but C++ is not) and using clever implementations (e.g. SBCL).

Consider also embedding some interpreter in your C++ program, perhaps Lua or Guile or Python. The interpreted script is then some input to your program and might run whatever code you interface to it. Read the Dragon Book.

Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
Basile Starynkevitch
  • 1
  • 16
  • 251
  • 479
0

Pretty much by using the virtual keyword. See this example:

#include <iostream>

using std::cout;
using std::endl;

class BaseClass {
  public:
    BaseClass() {}
    virtual ~BaseClass() {}

    void method1() { cout << "in superclass" << endl; }

    virtual void runAllMethods()
    {
        method1();
    }
};

class SubClass : public BaseClass {
  public:
    SubClass() {}
    virtual ~SubClass() {}

    void method2() { cout << "in subclass" << endl; }
    
    virtual void runAllMethods()
    {
        BaseClass::runAllMethods();
        method2();
    }
};

int main()
{
    BaseClass* obj = new SubClass;
    obj->runAllMethods();
    delete obj;
}

output:

in superclass
in subclass

This calls the runAllMethods method from the sub class which then again calls the sub class method and the super class runAllMethods.
If you need a slightly different architecture, best is if you state how the code that is to use it later should look like.

In action: http://cpp.sh/2mvvy

Edit: If you want some additional safety here, use override in the subclass:

virtual void runAllMethods() override

This warns you if the method does not actually override (like if you would have a parameter and you change it's type in the super class but not in the sub class, causing the methods to have different signature and thus won't override.)

Aziuth
  • 2,768
  • 1
  • 11
  • 25
  • `virtual` on methods in the derived class is redundant when you override. Adding `override` makes it an _error_ if it doesn't override. – Ted Lyngmo Jun 25 '20 at 08:13
  • @TedLyngmo Do you see this as bad style? I don't mind an edit if you do. My idea was to still signalize that `runAllMethods` is to be implemented by children, as in the question it sounds like there might be chains longer than two classes. Somebody deriving `SubClass`. For that reason, I'd only remove the `virtual` if I'd made the class `final`. But I'd like to hear what other people think about this, and again, feel free to edit. – Aziuth Jun 25 '20 at 08:24
  • I personally prefer to leave it out and just use `override` but I'm not sure I'd call it bad style. Perhaps a little :-) It'll be `virtual` no matter how deep the inheritance goes though, even if you leave it out: [demo](https://godbolt.org/z/T3QdkP) – Ted Lyngmo Jun 25 '20 at 08:32
  • How does that answers the question by OP? – Basile Starynkevitch Jun 25 '20 at 08:41
  • 1
    @BasileStarynkevitch Seeing the other answers and comments, I think they overinterprete what OP wants. They are going for complicated ways of reflection and the like, while it might easily be that OP simply wants some sort of structure in which a series of processing methods are executed. Which my code does. I might be wrong about what he wants, though. Let's wait for a reply from him. In any case, my answer *does* answer the question, as the method in the super class accesses the methods in the sub class. In a most simple way. Can delete my answer later on in any case. – Aziuth Jun 25 '20 at 08:58