在下面的代码中,我希望用户能够创建具有特定类型(例如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;
};
我该如何做?
答案 0 :(得分:2)
消耗方法来自基类,必须重写它们。 [...]我该如何做?
我认为可能的解决方案是开发两种consume_h()
(“消费助手”)方法。
第一个与调用回调函数的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
}