Callback.h

继承层次

  • CallBack实现类
基类 第一层子类 第二层子类 第三层子类
SimpleRefCount CallbackImplBase CallbackImpl FunctorCallbackImpl
MemPtrCallbackImpl
BoundFunctorCallbackImpl
TwoBoundFunctorCallbackImpl
ThreeBoundFunctorCallbackImpl
  • Callback封装类

    • CallbackBase 封装Ptr<CallbackImplBase> m_impl
    • Callback CallbackBase的子类。根据传入的不同实参,构造不同类型的callback。

模板整体说明

  • CallbackImpl:有不同的特化子模板

    • 根据重载()操作符时需要的形参类型个数将Ti~Tk特化为empty类,调用是根据传入的模板形参个数匹配相应的模板
    • R:回调返回值
  • FunctorCallbackImpl:CallbackImpl没有默认值,
    • T:泛函的类型(配套的,包括泛函返回类型,泛函形参类型)
  • MemPtrCallbackImpl:CallbackImpl
    • OBJ_PTR:object的类型
    • MEM_PTR:object成员泛函的类型(包括泛函返回类型,泛函形参类型)
  • BoundFunctorCallbackImpl: CallbackImpl

    • T:泛函类型
    • R:回调返回值
    • Tx:绑定的类型
    • 回调时,总有一个类型为Tx的值作为回调的形参
  • CallBack:T1~T9:默认值为empty类

  • MakeCallback<>模板函数:根据传入不同的形参,实例化不同版本

    • 形参:泛函指针

      • 根据传入的普通泛函涉及的类型个数(返回值类型,形参类型个数)匹配不同回调形参个数的模板
    • 形参:类成员泛函指针,类对象指针
      • 根据传入的类成员泛函的涉及的类型(返回值类型,形参类型个数)匹配不同回调形参的模板
    • 形参:泛函指针,绑定的值(1~3个)

CallbackTraits

  • 模板1 c++ template <typename T> struct CallbackTraits;
  • 将指针转化为引用,用于MemPtrCallBackImpl c++ template <typename T> struct CallbackTraits<T *> { static T & GetReference (T * const p){ return *p; } };

CallbackImplBase

class CallbackImplBase : public SimpleRefCount<CallbackImplBase>
{
public:virtual ~CallbackImplBase () {}// Equality testvirtual bool IsEqual (Ptr<const CallbackImplBase> other) const = 0;
};

CallbackImpl

通过重载函数操作符"()"实现
- 模板声明,该模板限定了最多能传入9个形参给callback

template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
class CallbackImpl;
  • 无参数特化模板
template <typename R>
class CallbackImpl<R,empty,empty,empty,empty,empty,empty,empty,empty,empty> : public CallbackImplBase {
public:virtual ~CallbackImpl () {}virtual R operator() (void) = 0;      //!< Abstract operator
};
  • 将模板形参T2~T9特例话为空 这是将基类模板中模板形参T2到T9特化为empty类型的一个例子(部分特化)
template <typename R, typename T1>
class CallbackImpl<R,T1,empty,empty,empty,empty,empty,empty,empty,empty> : public CallbackImplBase {
public:virtual ~CallbackImpl () {}virtual R operator() (T1) = 0;        //!< Abstract operator
};
  • 其他类似
  • CallbackImpl的定义
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
class CallbackImpl : public CallbackImplBase {
public:virtual ~CallbackImpl () {}virtual R operator() (T1, T2, T3, T4, T5, T6, T7, T8, T9) = 0;  //!< Abstract operator
};

FunctorCallbackImpl

CallbackImpl with functors
R:回调返回类型;
T :m_functor类型,T是一个函数指针的类型(包括函数形参列表,以及函数返回类型。而处于兼容性考虑,T应该是这样的类型 R(*)(T1,T2.......)

template <typename T, typename R, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6, typename T7, typename T8, typename T9>
class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> {
public:
FunctorCallbackImpl (T const &functor):m_functor(functor){}
virtual ~FunctorCallbackImpl () {}
//无输入参数的回调,
R operator() (void) {return m_functor (); }
//带一个形参的回调R operator() (T1 a1) {return m_functor (a1);  }
// 其他形参个数的回调类似
.......
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const{
FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6,T7,T8,T9>const *otherDerived =dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> const *> (PeekPointer (other));//把其他类型的CallbackImpl转换成FunctorCallbackImpl类
if (otherDerived == 0){return false;}
else if (otherDerived->m_functor != m_functor){return false;}
return true;
}
private:T m_functor;         //!< the functor
};

MemPtrCallbackImpl

CallbackImpl for pointer to member functions
模板形参MEM_PTR:类成员泛函的类型(涉及泛函返回类型,形参类型表等)

template <typename OBJ_PTR, typename MEM_PTR, typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> {
public:
MemPtrCallbackImpl (OBJ_PTR const&objPtr, MEM_PTR memPtr): m_objPtr (objPtr), m_memPtr (memPtr) {}virtual ~MemPtrCallbackImpl () {}//无形参成员函数回调实现R operator() (void) {return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr)();//将m_objPtr转换成引用并调用其成员函数(*m_memPtr)  //其他参数个数的成员函数的回调实现类似}.......virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> const *otherDerived=dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> const *> (PeekPointer (other));
if (otherDerived == 0){  return false;  }
else if (otherDerived->m_objPtr != m_objPtr||therDerived->m_memPtr != m_memPtr){return false;}
return true;
}
private:OBJ_PTR const m_objPtr;     //!< the object pointerMEM_PTR m_memPtr;        //!< the member function pointer
};

BoundFunctorCallbackImpl

CallbackImpl for functors with first argument bound at construction

 template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6, typename T7, typename T8>
class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,empty> {
public:
template <typename FUNCTOR, typename ARG>BoundFunctorCallbackImpl (FUNCTOR functor, ARG a): m_functor (functor), m_a (a) {}virtual ~BoundFunctorCallbackImpl () {}
//没有可变类型形参的函数调用
R operator() (void) {    return m_functor (m_a);  }
//有一个Arg的函数回调
R operator() (T1 a1) {  return m_functor (m_a,a1);  }
//其他Arg个数的模板类似
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const{
//实现和上面类似,先转换,然后比较
}
private:T m_functor;    //!< The functortypename TypeTraits<TX>::ReferencedType m_a;  //!< the bound argument
};

TwoBoundFunctorCallbackImpl

CallbackImpl for functors with first two arguments bound at construction

template <typename T, typename R, typename TX1, typename TX2, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6, typename T7>
class TwoBoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,empty,empty> {
....
private:T m_functor;              //!< The functortypename TypeTraits<TX1>::ReferencedType m_a1;  //!< first bound argumenttypename TypeTraits<TX2>::ReferencedType m_a2;  //!< second bound argument
};
}

ThreeBoundFunctorCallbackImpl

和上述类似

CallbackBase

class CallbackBase {
public:CallbackBase () : m_impl () {}Ptr<CallbackImplBase> GetImpl (void) const { return m_impl; }
protected:
CallbackBase (Ptr<CallbackImplBase> impl) : m_impl (impl) {}Ptr<CallbackImplBase> m_impl;         //!< the pimplstatic std::string Demangle (const std::string& mangled);//符号重组?这个干什么的呢?
};

CallBack类

  • 模板的示例化具有POD语义:需要的内存是自动管理的,并且允许用户传递一个CallBack实例
  • 模板使用pimpl idiom,传递CallBack类的值并将实现传递给其pimpl指针
  • CallbackImpl和 FunctorCallbackImpl的子类可用于任何functor-type,而 MemPtrCallbackImpl 可用于某一个类的成员函数指针
  • 通过reference list implementation实现CallBack类的值语义 ####Callback的构造函数
  • 空构造函数 Callback () {}
  • 根据 Ptr构建Callback c++ Callback (Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > const &impl): CallbackBase (impl){}
  • 内置类型为FunctorCallbackImpl 创建一个FunctorCallbackImpl的实例(第一参数特化为iFUNCTOR类型,其他分别是R,T1等)。创建Create模板函数的此FunctorCallbackImpl的实例,给函数传入实参functor,创建对应的Ptr的关于FunctorCallbackImpl的实例,将此Ptr对象作为CallBackBase类的构造函数实参
template <typename FUNCTOR>Callback (FUNCTOR const &functor, bool, bool) : CallbackBase(Create<FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > (functor)){}
  • 内置类型为MemPtrCallbackImpl 实例化MemPtrCallbackImpl,创建一个此类型的ptr,传给Create函数的实参为objPtr和memPtr
template <typename OBJ_PTR, typename MEM_PTR>Callback (OBJ_PTR const &objPtr, MEM_PTR memPtr):CallbackBase (Create<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > (objPtr, memPtr)){}

Callback的绑定

  • Bind

    • 构造一个绑定第一个Arg的回调
    • 实例化一个BoundFunctorCallbackImpl,实例化传入的模板实参解释
      • Callback<R,T1,T2,T3,T4,T5,T6,T7,T8,T9>BoundFunctorCallbackImpl内置泛函类型
      • R:回调的返回类型
      • T1:绑定的类型
      • T2~T9:其他可控的函调形参类型
    • 创建上述BoundFunctorCallbackImpl实例类的一个对象
      • 传给类的构造函数的实参:(*this):BoundFunctorCallbackImpl的内部泛函
      • a :绑定的值
    • 创建Ptr>对象impl
      • 传给Ptr构造函数的实参:上面创建的BoundFunctorCallbackImpl实例类临时对象和false
    • 以impl为实参构建Callback对象
template <typename T>
Callback<R,T2,T3,T4,T5,T6,T7,T8,T9> Bind (T a) {Ptr<CallbackImpl<R,T2,T3,T4,T5,T6,T7,T8,T9,empty> > impl =Ptr<CallbackImpl<R,T2,T3,T4,T5,T6,T7,T8,T9,empty> > (new BoundFunctorCallbackImpl<Callback<R,T1,T2,T3,T4,T5,T6,T7,T8,T9>,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> (*this, a), false);return Callback<R,T2,T3,T4,T5,T6,T7,T8,T9> (impl);}
  • 绑定前两个 实现与Bind类似
template <typename TX1, typename TX2>
Callback<R,T3,T4,T5,T6,T7,T8,T9> TwoBind (TX1 a1, TX2 a2){..}
  • 绑定前三个

    实现与上面类似

template <typename TX1, typename TX2, typename TX3>Callback<R,T4,T5,T6,T7,T8,T9> ThreeBind (TX1 a1, TX2 a2, TX3 a3){...}

Callback的其他成员函数函数

template<typename R,typename T1 = empty, typename T2 = empty,typename T3 = empty, typename T4 = empty,typename T5 = empty, typename T6 = empty,typename T7 = empty, typename T8 = empty,typename T9 = empty>
class Callback : public CallbackBase {
public:
bool IsNull (void) const {return (DoPeekImpl () == 0) ? true : false;}void Nullify (void) {m_impl = 0;}//无输入参数的回调R operator() (void) const {return (*(DoPeekImpl ()))();}//输入一个参数的回调R operator() (T1 a1) const {return (*(DoPeekImpl ()))(a1);}// 其他输入参数个数的回调与上述类似bool IsEqual (const CallbackBase &other) const {return m_impl->IsEqual (other.GetImpl ());}//如果other能转换成我这种类型,返回truebool CheckType (const CallbackBase & other) const {return DoCheckType (other.GetImpl ());}void Assign (const CallbackBase &other) {DoAssign (other.GetImpl ());}private:CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> *DoPeekImpl (void) const {return static_cast<CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> *> (PeekPointer (m_impl));}//如果other能转换成我这种类型,返回truebool DoCheckType (Ptr<const CallbackImplBase> other) const {if (other != 0 && dynamic_cast<const CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> *> (PeekPointer (other)) != 0){  return true; //不为空且能转换    }else if (other == 0){ return true; //传入的Ptr为空 }else{   return false; }}void DoAssign (Ptr<const CallbackImplBase> other) {if (!DoCheckType (other)){Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > expected;NS_FATAL_ERROR (....);}m_impl = const_cast<CallbackImplBase *> (PeekPointer (other));}
}

MakeCallback模板函数

针对不同形参个数的函数指针的 MakeCallback函数模板

template <typename R>
Callback<R> MakeCallback (R (*fnPtr)()) {return Callback<R> (fnPtr, true, true);
}
template <typename R, typename T1>
Callback<R,T1> MakeCallback (R (*fnPtr)(T1)) {return Callback<R,T1> (fnPtr, true, true);
}
//其他类型函数指针的MakeCallback类似

针对不同形参个数的类成员函数指针的 MakeCallback函数模板

template <typename T, typename OBJ, typename R>
Callback<R> MakeCallback (R (T::*memPtr)(void), OBJ objPtr) {return Callback<R> (objPtr, memPtr);
}//const版本类似
template <typename T, typename OBJ, typename R, typename T1>
Callback<R,T1> MakeCallback (R (T::*memPtr)(T1), OBJ objPtr) {return Callback<R,T1> (objPtr, memPtr);
}
//其他类似
  • != 符号的重载

  • MakeNullCallback的定义

  • MakeBoundCallback的定义(包括绑定一个,两个等)

    CallBack类的和属性系统相关的东西

class CallbackValue : public AttributeValue
{
public:
CallbackValue ();CallbackValue (const CallbackBase &base);virtual ~CallbackValue ();void Set (CallbackBase base);template <typename T>bool GetAccessor (T &value) const;virtual Ptr<AttributeValue> Copy (void) const;virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const;virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);private:CallbackBase m_value;                 //!< the CallbackBase
};
ATTRIBUTE_ACCESSOR_DEFINE (Callback);
ATTRIBUTE_CHECKER_DEFINE (Callback);
//Assign和CheckType函数是callback的成员函数。因此T应该也是一张callback又是哪里定义的
template <typename T>
bool CallbackValue::GetAccessor (T &value) const
{if (value.CheckType (m_value)){value.Assign (m_value);return true;}return false;
}

Callback.cc

  • CallbackValue类成员函数的一些定义
  • 定义和Callback相关的checker
ATTRIBUTE_CHECKER_IMPLEMENT (Callback);

转载于:https://www.cnblogs.com/rainySue/p/callback-de-shi-xian.html

callback的实现相关推荐

  1. each(callback)与each(object[,callback])的区别

    each(callback)与each(object[,callback])的区别: 1. 调用对象不同,前者必须使用jQuery对象调用:后者只能使用$调用: 2. 遍历对象不同:前者遍历的是jQu ...

  2. dispatch callback ant design pro 网络请求回调函数

    index.jsx 代码解析:在组件初次渲染时调用 model 中 命名空间为  a_models  的 getData 网络请求,传了一个patload 参数和 callback 回调函数过去,然后 ...

  3. c++回调函数 callback

    (1)Callback方式 Callback的本质是设置一个函数指针进去,然后在需要需要触发某个事件时调用该方法, 比如Windows的窗口消息处理函数就是这种类型.比如下面的示例代码,我们在Down ...

  4. keras中的fit函数参数_keras的fit_generator与callback函数

    fit_generator函数 fit_generator函数 callback类 每一个epoch结束(on_epoch_end)时,都要调用callback函数,callback函数(类)都要集成 ...

  5. js callback回调的一种写法

    getLocation.cityname(latitude, longitude, function (data1) { SetCityCallBack(data1); }); 定义方法: var g ...

  6. Android Audio代码分析25 - JNI callback

    今天来说说 native 中的代码是如何调用 java 侧代码的. 在看 setEnabled 代码的时候,我们了解到,最终在函数 EffectHandle::setEnabled 中会调用 java ...

  7. java web自定义监听器_Android自定义监听器Listener(自定义Java Callback回调事件)

    Callback回调事件介绍 Java或Android中创建异步回调最普遍的做法就是使用listener监听器或者observer观察者模式来解决,listener回调事件通常用于实现一个代码去监听另 ...

  8. 【NIO】异步模型之Callback -- 封装NIO

    在[NIO]IO模型,这节课中,我们提到了5种IO模型.第四种,SIGIO一般都是在进程间使用信号通讯的时候的手段,在Java中不是很适用,我就不深入去讲了.第五种,linux 服务器上的典型代表是 ...

  9. js等待 callback 执行完毕_前端开发,一篇文章让你彻底搞懂,什么是JavaScript执行机制!...

    不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定的几行代码,我们需要知道其输出内容和顺序.因为javascript是一门单线程语言,所以我们可 ...

  10. 【js】callback时代的变更

    最近团队开始越来越多的使用es7标准的async/await,从最开始的promise到后面的generator,再到现在async,对于异步,每个时期都有着其特有的解决方案,今天笔者就以自己的接触为 ...

最新文章

  1. MySQL 唯一索引 UNIQUE KEY 会导致死锁?
  2. python模块导入
  3. 行为模式之Command模式
  4. Windows 2003 server 服务器集群实例
  5. 内建模块_月隐学python第14课
  6. What's NEW in C++/CLI Language
  7. 【图论】【Floyed】舞会邀请(CODE[VS] 2604)
  8. Java的注解机制——Spring自动装配的实现原理
  9. css控制div等比高度
  10. 做数据分析还在死磕Excel?用这个简单工具,摆脱复杂函数和公式
  11. 进行Java Web项目开发需要掌握的技术
  12. c++链接错误debug
  13. wireshark协议
  14. Hash冲突的四种解决办法
  15. android 工程模式设置中文翻译,MTK工程模式(中文对照版本)与测试模式指令.doc
  16. 如何理解CNN中的感受野(receptive-field)以及如何计算感受野?
  17. linux删除账号及主目录及邮箱,Linux 用户管理
  18. 我现在必须new一个对象!!!
  19. 存储过程和存储函数 练习
  20. 基于Java的人员信息管理系统

热门文章

  1. 在PTA中c语言中求连续因子,团体程序设计天梯赛-练习集L1-006. *连续因子
  2. sql查询分析器 只读_DRDS 只读实例来解决复杂 SQL 查询
  3. python实现简单购物商城_如何用python语言实现简单购物商城
  4. java 视频转码工具类_JavaCV入门指南:FrameConverter转换工具类及CanvasFrame图像预览工具类(javaCV教程完结篇)...
  5. 如何解决 Nginx 端口映射到外网后访问地址端口丢失的问题
  6. php两个字符串怎么比较,php比较两个字符串的函数strcasecmp()
  7. filazilla搭建ftp_使用Filezilla搭建FTP服务器
  8. vscode设置背景图片
  9. 把流量变现赚钱的一些想法
  10. java歌词高亮显示滚动_js如何处理音乐播放器的歌词文件达到高亮以及滚动的效果?...