C++:在基类中使用具有通用虚拟函数的异步回调

C++:Using asynchronous callbacks with generic virtual functions in a base class

本文关键字:虚拟 函数 回调 异步 基类 C++      更新时间:2023-10-16

目前我正在编写一个C++程序,该程序应该包含一个非常通用的基类。它将具有一些受保护的功能

class Base{
     virtual void doA() = 0;
     virtual void doB() = 0;
     \[see below]...
}

它们将异步执行,并在完成后立即将其作为回调调用:

 virtual void doACallback(type1 param1, type2 param2) = 0;
 virtual void doBCallback() = 0;

我的问题是,doAdoB的实现对于每个子类都是不同的,回调方法应该能够接收不同的参数(类型和数量)。在基类中保留回调方法声明的同时,是否可以管理它?也许这可以通过另一种方式来实现。我对C++还是个新手。

注意:Base不仅仅包含纯虚拟函数。

编辑:因为有些人问。我想定义子类的一般"外观"。我的具体场景非常复杂,但让我们举一个例子:

class Base{
  virtual void sendData() = 0;
  virtual void sendDataCallback() = 0;
}
class SubclassA:public Base{    
  void sendData() override{
       //send Data by using LibraryA
  }
  void sendDataCallback(ErrorCode aErrorCode) override{
     //handle error Code
  }    
}
class SubclassB:public Base{
  void sendData() override{
       //send Data by using LibraryB
  }
  void sendDataCallback(ErrorCode aErrorCode, Response aResponse) override{
     //handle error Code and handle response
  }    
}

这不是确切的场景,但也许这澄清了这个想法。。。

编辑2:如果有人想知道:最后我选择在子类中定义回调。

几乎任何事情都是可能的。您可以转换为void*并返回到派生类中:

struct ScrewThis
{
    void addCallback(void * cb) { callbacks.push_back(cb); }
    void executeCallback(int index) const = 0;
    std::vector<void*> callbacks;
};
struct TotalHell : ScrewThis
{
    void executeCallback(int index) const
    {
        auto callback
             = static_cast<std::function<int(int,int)> const*>(callbacks[index]);
        auto i = callback(4,2);
        //...
     }
};

但你为什么要这么做?这是一场维护噩梦。其他开发者会看到它,立刻想自杀。。。或者你。。。。或者更有可能两者兼而有之。

你这样做只是为了共享"通用"代码吗?(在恐吓引号中的"通用"是因为你可以看到它不是通用代码)。OOP早期犯下的一个巨大错误是认为继承是为了增加重用。这是错误的。您可以通过组合来增加重用。

当你最终不得不重新实现多态性来做你想做的事情时,是时候想想了,也许你试图做的事情不是你应该做的。

您是否考虑过使用Command模式作为回调?派生类(从基类派生)应该使用CommandA和CommandB类来执行所需的行为。

class Command
{
    public:
    virtual void execute() = 0;
};
class CommandA : public Command
{
    public:
    CommandA();
    void execute() override;
};
class CommandB : public Command
{
    public:
    CommandB(int param1, double param2);
    void execute() override;
};

然后是混凝土等级:

class Concrete : public Base
{
    public:
    Concrete(Command* callA, Command* callB): callbackA(callA), callbackB(callB)
    {}
    void doA()override
    {
         ...
         callbackA->execute();
    }
    void doB()override
    {
         ...
         callbackB->execute();
    }
    private:
    Command* callbackA;
    Command* callbackB;
};

不,这是不可能的。我也不认为这有什么意义。实现回调的子类无论如何都必须从包含do函数实际实现的类派生,所以我不明白为什么具有do实现的类不能声明回调函数。