gpt4 book ai didi

c++ - 模板基类 C++ 中的重写函数指针问题

转载 作者:行者123 更新时间:2023-11-30 04:40:22 25 4
gpt4 key购买 nike

我为观察者模式实现了一个模板基类,

template<class T>
class ActionListener
{
public:
ActionListener(void);
virtual ~ActionListener(void);
void registerListener(T* listener);
void unregisterListener(T* listener);

template<typename Signal>
void emit(Signal signal);

template<typename Signal, typename Parameter>
void emit(Signal signal, const Parameter& parameter);

template<typename Signal, typename Parameter1, typename Parameter2>
void emit(Signal signal,
const Parameter1& parameter1,
const Parameter2& parameter2);

private:
std::vector<T*> mListenerList;
};

class IEventListener
{
public:
virtual void messageArrived( Message* message);
virtual void messageArrived(ClientHandle* handle, Message* message);
};

我正在使用这样的类

emit(&IEventListener::messageArrived, message);
emit(&IEventListener::messageArrived, mHandle, message);

这里的问题是,编译器无法推导出模板参数,我也无法显式地给出模板参数?

有人有想法吗??

编辑:这里的问题是使用模板参数调用覆盖函数。“Emit”函数对于其他函数类型可以正常工作。

这个模式的用法是

class SampleClass : public ActionListener<IEventListener>
{
//some stuff here
//this class is observing events of IEventListener
}

顺便说一句,这是 C++。

最佳答案

IEventListener::messageArrived 被重载,因此编译器无法确定 &IEventListener::messageArrived 的类型。它可以是 void (IEventListener::*)(Message*)void (IEventListener::*)(ClientHandle*, Message*)

直接(和丑陋)的解决方案是在调用站点显式地将 &IEventListener::messageArrived 转换为所需的类型,如下所示:

emit(static_cast<void (IEventListener::*)(Message*)>(&IEventListener::messageArrived), a_message_ptr);

或通过分配给所需函数类型的变量:

void (IEventListener::*func_ptr)(Message*) = &IEventListener::messageArrived;
emit(func_ptr, a_message_ptr);

(我有说丑吗?)

也可以显式指定模板参数:

emit<void (IEventListener::*)(Message*)>(&IEventListener::messageArrived, a_message_ptr);

(还是丑)

另一个不完美的解决方案是从监听器类型 (T) 和其他参数推断出 Signal 的类型:

// Warning: untested. 
// For illustration purposes only
template<class T>
class ActionListener
{
public:
//...
void emit(void (T::*signal)());

template<class Arg1T>
void emit(void (T::*signal)(Arg1T), Arg1T);

template<class Arg1T, class Arg2T>
void emit(void (T::*signal)(Arg1T, Arg2T), Arg1T, Arg2T);
};

但这并不完美,因为参数类型必须完全匹配。

根据您可以在设计中进行多少更改,更简单的解决方案是通过为 IEventListener 的成员指定不同的名称来消除歧义。您还可以使用现有的信号/插槽库,例如 Boost.Signals2

关于c++ - 模板基类 C++ 中的重写函数指针问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1466163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com