【问题标题】:C++ template class with dynamic callback function type具有动态回调函数类型的 C++ 模板类
【发布时间】:2019-04-18 02:05:24
【问题描述】:

在下面的代码中,我希望用户能够创建具有特定类型的消费者类,例如Consumer<StateA>,以便他们的回调函数可以正确处理他们提供的类型。但是在下面的代码中,编译器会抱怨,因为在编译时,没有生成对 StateB 消费方法中的函数的调用。消费方法来自基类,它们必须被覆盖。

template <class T>
class Consumer : ConsumerBase
{
    public:
        Consumer(std::function<void(T&)> _callback){
            callback = _callback;
        }
        virtual void consume(StateA& state) { 
            callback(state);
        }
        virtual void consume(StateB& state) { 
            callback(state);
        }
    private:
        std::function<void(T&)> callback; 
};

基类:

class ConsumerBase
{
   public:
      virtual void consume(StateA& state) = 0;
      virtual void consume(StateB& state) = 0;
};

我怎样才能做到这一点?

【问题讨论】:

  • 尽我所能理解这个问题,子类只需要声明一个consume() 方法,带有T &amp; 参数,这样它就可以覆盖超类中的等效方法(以及声明应该使用override 关键字而不是virtual,以帮助您的编译器捕获代码中的错误)。如果超类仅定义抽象方法,则需要使用不同的方法,但是由于您的问题缺少 minimal reproducible example,如 stackoverflow.com 的 help center 中所述,无法提供进一步的建议。
  • @SamVarshavchik 谢谢,我已经添加了基类,它具有必须覆盖的纯虚函数。
  • 我怀疑不是consume(StateB&amp;)没有生成,而是无法编译。在Consumer&lt;StateA&gt; 中没有callback(StateB&amp;),唯一可见的callback 采用StateA&amp;,因此您无法编译定义。
  • @jthill 是的,你是对的。我的意思是说(由编译器)找不到对(回调)函数的调用,因为没有使用 StateB 生成的回调函数。

标签: c++ c++11 templates callback pure-virtual


【解决方案1】:

consume 方法来自一个基类,它们必须被覆盖。 [...] 我怎样才能完成这项工作?

我想一个可能的解决方案是开发几个consume_h()(“consume helper”)方法。

第一个与调用回调函数的T(类的模板类型)完全匹配

    void consume_h (T & state)
     { callback(state); }

第二个是什么都不做的模板版本

    template <typename U>
    void consume_h (U &)
     { }

现在你可以覆盖两个虚方法调用consume_h()

    virtual void consume (StateA & state)
     { consume_h(state); }

    virtual void consume (StateB & state)
     { consume_h(state); }

这种方式对应T的虚方法,调用回调的consume_h();另一个调用模板consume_h() 什么都不做。

以下是完整的编译示例

#include <functional>

struct StateA { };
struct StateB { };

struct ConsumerBase
 {
   virtual void consume (StateA &) = 0;
   virtual void consume (StateB &) = 0;
 };

template <typename T>
class Consumer : ConsumerBase
{
    public:
        Consumer (std::function<void(T&)> cb0) : callback{cb0}
         { }

        void consume_h (T & state)
         { callback(state); }

        template <typename U>
        void consume_h (U &)
         { }

        virtual void consume (StateA & state)
         { consume_h(state); }

        virtual void consume (StateB & state)
         { consume_h(state); }

    private:
        std::function<void(T&)> callback; 
};

int main()
{
   Consumer<StateA>  csa{[](StateA &){ std::cout << "A" << std::endl; }};
   Consumer<StateB>  csb{[](StateB &){ std::cout << "B" << std::endl; }};

   StateA  sa;
   StateB  sb;

   csa.consume(sa);  // print A
   csb.consume(sb);  // print B
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多