我有两个类:CFileFinderThread
封装了一个工作线程,CFileFinderCallbackForwarder
将线程数据转发给几个可能的外部回调函数之一(具有不同的签名)。回调函数的类型是转发器的模板参数。
CFileFinderCallbackForwarder<zCallBack> forwarder(zcallback);
CFileFinderThread<zCallBack> thread(forwarder);
while (thread.WaitForThread(0) != WAIT_OBJECT_0)
{
bool eventSignaled = ::WaitForSingleObject(forwarder.getCallbackSignal(),
DEFAULT_CALLBACK_MILLIS)
== WAIT_OBJECT_0;
forwarder.ExternalCallback(eventSignaled);
}
线程类保留对转发器实例的引用,并调用转发器中的方法以将数据存储在其中 - 但只有方法不以任何方式使用模板参数。唯一取决于模板参数的方法是ExternalCallback
。
是否可以避免使用转发器使用的回调函数的类型来模拟线程类?
或者替代方案是什么?因为线程真的不应该关心转发器将对其数据做什么。
答案 0 :(得分:0)
将您的转发器类划分为非泛型基类和通用派生类。显然,非通用基类应包含所有非通用数据和操作;派生类应包含ExecuteCallback
函数。
这允许您使线程类也是非泛型的。
这是一个简化但完整的例子:
// non-generic base:
class CFileFinderCallbackForwarderBase
{
private:
int i;
protected:
// making the constructor protected here is just good practice:
CFileFinderCallbackForwarderBase() {}
public:
void SetData() { i = 0; }
};
// thread class is now non-generic
class CFileFinderThread
{
private:
// thread class is non-generic because it only uses
// the base class:
CFileFinderCallbackForwarderBase* forwarder;
public:
CFileFinderThread(CFileFinderCallbackForwarderBase* forwarder) :
forwarder(forwarder)
{
}
void f()
{
forwarder->SetData();
}
};
// derived class is generic:
template <class T>
class CFileFinderCallbackForwarder : public CFileFinderCallbackForwarderBase
{
public:
void ExternalCallback()
{
T t;
t = 0;
}
};
int main()
{
CFileFinderCallbackForwarder<int> forwarder;
CFileFinderThread thread(&forwarder);
forwarder.ExternalCallback();
}
这种技术的积极副作用可能是减少代码膨胀。