1

I have a abstract base class called Command that acts as an interface for commands that can be put in a queue:

class Command
{
public:

    Command(Dependency1& d1, Dependency2& d2);

    //...Irrelevant code removed for simplicity...

private:

    //Implementations do their work in their override of operator()
    virtual void operator()() = 0;
};

Then I have the declarations for the implementations in a header file:

class FooCommand : public Command
{
public:

    using Command::Command;

private:

    void operator()() override; 
};

class BarCommand : public Command
{
public:

    using Command::Command;

private:

    void operator()() override; 
};

class BazCommand : public Command
{  
public:

    using Command::Command;

private:

    void operator()() override; 
};

//...And many more...

So now I have a long list of near identical class declarations, only the name differs a bit. What would be the preferred ways to clean this up besides C style macro's?

Christophe
  • 68,716
  • 7
  • 72
  • 138
Unimportant
  • 2,076
  • 14
  • 19
  • 5
    Do you need to use inheritance? What about function pointers, lambda expressions, or `std::function`? – Cruz Jean Mar 31 '19 at 21:19

2 Answers2

2

It all depends on what you need to do in your operator().

If you don't need any access to the Command's state, then you could opt to pass a callable to the constructor. Like here:

class CallCommand : public Command { 
    std::function<void()> f;
public:
    CallCommand(Dependency1& d1, Dependency2& d2, std::function<void()> f) : Command(d1,d2), f(f) {
    }
private:
    void operator()() override { f(); }
};

You could then call it by providing either a free function, a lambda, or any std::function object. For example:

CallCommand c(d1,d2, [](){ cout<<"Hello world"<<endl;}); 

But if you need to access the class context, then I'm affraid there's no way around a real overriding like you did (and macro is an awful work around for the boilerplate code).

Christophe
  • 68,716
  • 7
  • 72
  • 138
1

The answer is similar to what has been answered by Cristophe but does not use inheritance.

You probably don't need inheritance. Instead, you could use std::function or lambda expressions. See, for example:

class Command
{
private:
  std::function<void()> f;
public:
  Command(Dependency1& d1, Dependency2& d2, std::function<void()> f): d1(d1), d2(d2), f(f) {}

  void operator()() {
    f();
  }
};

You could then create objects of Command and use them wherever in a queue or vector as desired.

Command call1(0, 0, []() {
  std::cout << "call1" << std::endl;
});
Command call2(0, 0, []() {
  std::cout << "call2" << std::endl;
});
std::vector<Command> v;
v.emplace_back(call1);
v.emplace_back(call2);
for (size_t i = 0; i < v.size(); i++) {
  v[i]();
}

Pre c++11, you can avoid inheritance by creating function pointers to each function and pass those pointers to the Command constructor.

Mukul Gupta
  • 2,310
  • 3
  • 24
  • 39