Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以避免模板化需要模板化成员的类吗?_C++_Templates - Fatal编程技术网

C++ 我可以避免模板化需要模板化成员的类吗?

C++ 我可以避免模板化需要模板化成员的类吗?,c++,templates,C++,Templates,我有两个类:CFileFinderThread封装工作线程和CFileFinderCallbackForwarder将线程数据转发到几个可能的外部回调函数(具有不同的签名)之一。回调函数的类型是转发器的模板参数 CFileFinderCallbackForwarder<zCallBack> forwarder(zcallback); CFileFinderThread<zCallBack> thread(forwarder); while (thread.WaitForT

我有两个类:
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);
}
CFileFinderCallbackForwarder货运代理(zcallback);
CFileFinderThread螺纹(转发器);
while(thread.WaitForThread(0)!=WAIT\u对象\u 0)
{
bool eventSignaled=::WaitForSingleObject(forwarder.getCallbackSignal(),
默认值(单位:毫秒)
==等待对象0;
转发器外部回调(eventSignaled);
}
thread类保留对转发器实例的引用,并调用转发器中的方法在其中存储数据,但仅限于不以任何方式使用模板参数的方法。根据模板参数实际不同的唯一方法是
ExternalCallback

是否可以避免使用转发器使用的回调函数类型模板化线程类?


或者有什么替代方案?因为线程根本不应该关心转发器将如何处理其数据。

将转发器类划分为非泛型基类和泛型派生类。显然,非泛型基类应该包含所有非泛型数据和操作;派生类应包含
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();
}
//非泛型基:
类CFileFinderCallbackForwarderBase
{
私人:
int i;
受保护的:
//在此处保护构造函数只是一种良好的做法:
CFileFinderCallbackForwarderBase(){}
公众:
void SetData(){i=0;}
};
//线程类现在是非泛型的
类CFileFinderThread
{
私人:
//thread类是非泛型的,因为它只使用
//基类:
CFileFinderCallbackForwarderBase*货运代理;
公众:
CFileFinderThread(CFileFinderCallbackForwarderBase*转发器):
货运代理(货运代理)
{
}
void f()
{
转发器->设置数据();
}
};
//派生类是泛型的:
模板
类CFileFinderCallbackForwarder:公共CFileFinderCallbackForwarderBase
{
公众:
void ExternalCallback()
{
T;
t=0;
}
};
int main()
{
CFileFinderCallbackForwarder货运代理;
CFileFinderThread线程(和转发器);
forwarder.ExternalCallback();
}

这种技术的一个积极的副作用可能是减少代码膨胀。

我很确定您可以使用它。如果您是指“成员变量”,则不可以。如果你的意思是“成员函数”,是的,你可以。@Puppy:这就是为什么我说“可能是”。这只是一个副作用。OTOH,也许OP目前有数百个实例化…:)你真的因为最后的声明而否决了答案吗?这可能是一个值得怀疑的问题,尽管所有的花言巧语,但我想知道这项技术本身是否有问题。我做到了,这是因为可怕的愚蠢的代码膨胀评论。@小狗:让我们暂时把代码膨胀这一行放在一边,尽管你的评论语气出人意料地侮辱。但是在OP的情况下,这个解决方案到底有什么可怕的地方呢?您似乎所做的只是重新实现了std::function,但效果很差。