当前正在尝试为SDL项目实现事件处理程序。总体思路是,用户输入事件将通过Message
对象进行处理,这些对象将能够携带具有不同签名的回调。目前,我拥有的是:
#pragma once
#include<functional>
#include"Entity.h"
#include"Enums.h"
typedef std::function<void(void)> VoidCallback;
typedef std::function<void(const Entity& entity)> EntityCallback;
template<typename Functor>
class Message
{
private:
MessageType message;
public:
Message(MessageType message, Functor callback) :message(message), callback(callback) {};
~Message();
};
但是,这种安排使得很难将不同类型的回调传递给不同的侦听器。当前的监听器实现是
#include"Message.h"
class Listener
{
public:
virtual void onNotify(Message<>& event) = 0;
};
这会导致错误。解决此问题的最佳方法是什么?
答案 0 :(得分:1)
您不能具有模板虚拟功能
Can a C++ class member function template be virtual?
#include "Message.h"
class Listener
{
public:
//you may use a template function as such
template<class func>
void onNotify(Message<func>& event) { /*must implement*/ }
//or specialize for specific function calls
virtual void onNotify(Message<some_known_func>& even) = 0;
};
如果您想使用具有类似虚拟功能的模板方法,可能会对研究CRTP感兴趣。 (CRTP使超类可以调用子类的方法)
答案 1 :(得分:1)
无法对虚拟功能进行模板化。
通过vtable
调用虚拟函数,该{基本上是函数指针的数组。基类中的每个虚拟方法都占用虚拟表中的一个插槽。显然,虚拟表的大小需要在编译时就知道,因为它是对象定义的一部分。
class Base {
public:
virtual void hello(){};
virtual void bye(){};
}
vtable可能如下所示:
hello
的指针。bye
的指针。因此vtable需要2个函数指针。
现在如果要hello()
或bye()
进行模板化,我们如何创建一个vtable?
hello<int>()
的指针hello<char>()
的指针。我们无法预先知道模板化函数的所有变体,因此无法构建vtable。