读书人

C++0x实践:function组合bind巧封装回

发布时间: 2012-09-10 22:20:12 作者: rapoo

C++0x实践:function结合bind巧封装回调函数
很喜欢function,但之前没认真思考,总感觉在使用bind绑定时很麻烦,所以有抵触情绪,有时宁可使用函数指针或thunk。今天又想起这个问题,并且尝试了一下将bind部分封装到类里:如能实现,外部接口只需要将需要回调的函数名传递进去即可。
经过一番努力,使用模板类实现了。
主要代码:

C/C++ code
namespace qp{class Search{public:    Search() : m_func(NULL)    {}    template <typename T1, typename T2>    void RegisterNotify(T1 memberFunc, T2* pThis)    {        m_func = std::bind(memberFunc, pThis, std::placeholders::_1, std::placeholders::_2);    }    template <typename T>    void RegisterNotify(T globalFunc)    {        m_func = std::bind(globalFunc, std::placeholders::_1, std::placeholders::_2);    }    bool Run()    {        if (m_func != NULL) return m_func(_T("Hello World!"), NULL);        return false;    }private:    typedef std::function<bool (qp::String fileOrPath, void* pUserData)> NotifyFunc;    NotifyFunc m_func;};} // namespace qp

C/C++ code
class A{public:    A()    {        ss.RegisterNotify(&A::SearchFiles, this);        ss.Run();    }    bool SearchFiles(qp::String fileOrPath, void* pUserData)    {        std::cout << pUserData << fileOrPath << std::endl;        return true;    }private:    qp::Search ss;};bool SearchFiles(qp::String fileOrPath, void* pUserData){    std::cout << "SearchFiles\n";    return true;}int _tmain(int argc, TCHAR* argv[]){    A a;    qp::Search ss;    ss.RegisterNotify(&SearchFiles);    ss.Run();    return 0;}

其中,qp::String可以替换成std::string。
总体来看,接口是简洁好用的,用户只需要调用RegisterNotify注册回调函数。
请用VS2008SP1以上、MinGW 4.4以上编译器编译。

[解决办法]
感觉还行吧, 给一个可以在VS2010上跑的版本

C/C++ code
#include <iostream>#include<vector>   #include<algorithm>   #include <functional>#include <string>using namespace std;   using namespace std::tr1;namespace qp{class Search{public:    Search() : m_func(NULL)    {}    template <typename T1, typename T2>    void RegisterNotify(T1 memberFunc, T2* pThis)    {        m_func = std::bind(memberFunc, pThis, std::placeholders::_1, std::placeholders::_2);    }    template <typename T>    void RegisterNotify(T globalFunc)    {        m_func = std::bind(globalFunc, std::placeholders::_1, std::placeholders::_2);    }    bool Run()    {        if (m_func != NULL) return m_func(string("Hello World!"), NULL);        return false;    }private:    typedef std::function<bool (std::string fileOrPath, void* pUserData)> NotifyFunc;        NotifyFunc m_func;};} // namespace qpclass A{public:    A()    {        ss.RegisterNotify(&A::SearchFiles, this);        ss.Run();    }    bool SearchFiles(string fileOrPath, void* pUserData)    {        std::cout << pUserData << fileOrPath << std::endl;        return true;    }private:    qp::Search ss;};bool SearchFiles(string fileOrPath, void* pUserData){    std::cout << "SearchFiles\n";    return true;}int _tmain(int argc, _TCHAR* argv[]){     A a;    qp::Search ss;    ss.RegisterNotify(&SearchFiles);    ss.Run();    return 0;}
[解决办法]
把楼主的搜索函数改了一下,不知道楼主有何见解:
C/C++ code
            void Search:: DoFileEnumeration(const qp::String strPath, bool bRecursion, bool bEnumFiles, void* pUserData)            {                try                {                    if (m_bUserBreak) return;                    WIN32_FIND_DATA fd;                    HANDLE hFindFile = ::FindFirstFile(qp::Path::Append(strPath, _T("*")).c_str(), &fd);                    if (hFindFile == INVALID_HANDLE_VALUE)                    {                        ::FindClose(hFindFile);                        return;                    }                    do                    {                        const qp::String fileName(fd.cFileName);                        qp::String tmpPath = qp::Path::Append(strPath, fileName);                        if (isDirectory && (fileName == _T(".") || fileName == _T("..")))                        {                            continue;                        }                        if (bEnumFiles != isDirectory)                        {                            qpASSERT(m_func);                            if (m_func && m_func(tmpPath, pUserData) == false)                            {                                m_bUserBreak = true;                                ::FindClose(hFindFile);                                return;                            }                        }                        if (isDirectory && bRecursion)                        {                            DoFileEnumeration(tmpPath, bRecursion, bEnumFiles, pUserData);                        }                    } while(::FindNextFile(hFindFile, &fd));                    ::FindClose(hFindFile);                }                catch (...)                {                    qpASSERT(false);                    qp::Debug::OutputString(_T("qp::Search's DoFileEnumeration throw Exception."));                    return;                }            } 

读书人网 >C++

热点推荐