简体   繁体   English

为实现接口的类避免多个几乎相同的声明

[英]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: 我有一个名为Command的抽象基类,它充当可以放入队列的命令的接口:

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? 除了C风格的宏之外,最好的方法是什么呢?

It all depends on what you need to do in your operator() . 这完全取决于您在operator()需要做什么。

If you don't need any access to the Command 's state, then you could opt to pass a callable to the constructor. 如果您不需要任何访问Command的状态,那么您可以选择将callable传递给构造函数。 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. 然后,您可以通过提供自由函数,lambda或任何std::function对象来调用它。 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). 但是如果你需要访问类上下文,那么我很担心没有办法像你那样绕过真正的重写(而宏是一个非常糟糕的解决样板代码的工作)。

The answer is similar to what has been answered by Cristophe but does not use inheritance. 答案与Cristophe所回答的类似,但不使用继承。

You probably don't need inheritance. 您可能不需要继承。 Instead, you could use std::function or lambda expressions. 相反,您可以使用std::functionlambda表达式。 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对象,并根据需要在queuevector任何位置使用它们。

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. 在前面的c++11 ,您可以通过创建每个函数的函数指针来避免继承,并将这些指针传递给Command构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM