Search code examples
c++classdeclarationdryclass-design

Avoiding multiple near identical declarations for classes that implement a interface


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?


Solution

  • 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).