template <class T> struct base { void interface() { static_cast<T*>(this)->implementation(); } void implementation(); ... }; struct derived : base<T> { void implementation(); ... }; 定义了一个基类模板 和 一个基类模板的派生类。 这两个类中都有 void implementation()函数,而且在基类的void interface()接口函数中用一个静态指针指向了implementation()函数。 实例化一个基类,并将派生类作为基类的参数。 复制base<derived> base_t; base_t.implementation(); 调用基类的implementation()成员函数,这时是调用的基类中的implementation()函数 还是派生类中的implementation()函数呢? 由于我们已经在derived派生类中定义了implementation()函数,并且base类实例化时的参数指向了derived派生类。 所以base_t.implementation()调用的是派生类derived中的成员函数implementation()。 如果派生类derived中没有定义implementation()成员函数, 那么base_t.implementation()调用的是基类base中的成员函数implementation()。 因此,base类模板既可以调用当前的成员函数,还可以调用未来(派生类)的成员函数。 此特性称为“静态多态”,CRTP即使实现一种静态的多态效应。 2、上面已经描述了CRTP的基本使用。现在我们来做一个基于单片机的小项目,这里使用的新唐的NU_Tiny-EVB_120和 keil开发环境。本项目是一个CO探测器,其工作流程非常简单。 探测器自检初始化 ---> 传感器检测当前环境CO含量并发出状态警告 ---> 进入低功耗模式 ---> 30秒后唤醒单片机,传感器再次检测当前环境CO含量并发出状态警告 ---> 进入低功耗模式 ...以此循环。 先给出基于CRTP的基本框架。 复制//detector.h #ifndef __Detector_H__ #define __Detector_H__ #include "routine.h" template<typename T> struct detector { void fun() { static_cast<T*>(this)->detector_init(0,"__DATE__"); for(;;){ static_cast<T*>(this)->detector_poll(); static_cast<T*>(this)->power_down(); } } void detector_poll() { while( static_cast<T*>(this)->power_scan() ); static_cast<T*>(this)->sensor_scan(); static_cast<T*>(this)->danger_warn(); static_cast<T*>(this)->dev_state(); } void detector_init(int, char*); int power_scan(); void power_down(); void danger_warn(); void dev_state(); void sensor_scan(); }; template<typename T> void detector<T>::detector_init(int, char*) { } template<typename T> void detector<T>::power_down() { } template<typename T> int detector<T>::power_scan() {return 0;} /*xx厂家传感器*/ template<typename T> void detector<T>::sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } template<typename T> void detector<T>::danger_warn() { } template<typename T> void detector<T>::dev_state() {} /*----------------------------------------------------------------------------*/ /*yy厂家传感器*/ struct detector_a:detector<detector_a> { /*void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 }*/ }; #endif //main.cpp #include"detector.h" int main (void) { __enable_irq(); detector<detector_a> co_star; co_star.fun(); while(1) { } } 为了方便阅读,我删除了函数中具体的内容,只留下了一个最小框架。 复制detector<detector_a> co_star; co_star.fun(); 主函数中实例化了一个探测器co_star模板类,并且参数指向了detector模板的派生类detector_a, 由于我们使用的传感器类型较多,每个厂家,每个型号 的传感器的工作方式又可能不尽相同。 所以我在detector模板中预留了一种传感器(xx厂家的传感器),其扫描方式为detector<T>::sensor_scan()。 其后因市场原因,又需要使用yy厂家的传感器,所以我在detector模板的基础上派生了一个detector_a类, 同样定义yy的扫描方式为sensor_scan(),只是在detector实例化的时候,将参数指向了detector_a . 复制/*yy厂家传感器*/ struct detector_a:detector<detector_a>{ void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } 所以主函数中co_star.fun()调用的detector<detector_a>::sensor_scan()其实是指向了yy厂家传感器的扫描方式 detector_a::sensor_scan()。 这里不仅仅传感器扫描可以通过CRTP来拓展,从fun() 到 detector_poll() 到 sensor_scan() 全都可以通过CRTP的静态多态效应来拓展/重构。 复制struct detector_a:detector<detector_a>{ void fun() { ... } struct detector_a:detector<detector_a>{ void detector_poll() { ... } 从整个框架到一个内部函数都可用这种机制来拓展/重构,其可拓展的粒度可以是一个最小的函数调用。现在你可否体会到C++ CRTP模式的程序拓展呢? 本帖测试源代码也上传至此,具体的函数实现被我删掉了,仅以一个io翻转来做演示,请见谅。 如果您还想深入了解CRTP框架的嵌入式软件设计,可以看看john_lee老师的课程记录 https://bbs.21ic.com/icview-577248-1-1.html
base<derived> base_t; base_t.implementation(); 调用基类的implementation()成员函数,这时是调用的基类中的implementation()函数 还是派生类中的implementation()函数呢? 由于我们已经在derived派生类中定义了implementation()函数,并且base类实例化时的参数指向了derived派生类。 所以base_t.implementation()调用的是派生类derived中的成员函数implementation()。 如果派生类derived中没有定义implementation()成员函数, 那么base_t.implementation()调用的是基类base中的成员函数implementation()。 因此,base类模板既可以调用当前的成员函数,还可以调用未来(派生类)的成员函数。 此特性称为“静态多态”,CRTP即使实现一种静态的多态效应。 2、上面已经描述了CRTP的基本使用。现在我们来做一个基于单片机的小项目,这里使用的新唐的NU_Tiny-EVB_120和 keil开发环境。本项目是一个CO探测器,其工作流程非常简单。 探测器自检初始化 ---> 传感器检测当前环境CO含量并发出状态警告 ---> 进入低功耗模式 ---> 30秒后唤醒单片机,传感器再次检测当前环境CO含量并发出状态警告 ---> 进入低功耗模式 ...以此循环。 先给出基于CRTP的基本框架。 复制//detector.h #ifndef __Detector_H__ #define __Detector_H__ #include "routine.h" template<typename T> struct detector { void fun() { static_cast<T*>(this)->detector_init(0,"__DATE__"); for(;;){ static_cast<T*>(this)->detector_poll(); static_cast<T*>(this)->power_down(); } } void detector_poll() { while( static_cast<T*>(this)->power_scan() ); static_cast<T*>(this)->sensor_scan(); static_cast<T*>(this)->danger_warn(); static_cast<T*>(this)->dev_state(); } void detector_init(int, char*); int power_scan(); void power_down(); void danger_warn(); void dev_state(); void sensor_scan(); }; template<typename T> void detector<T>::detector_init(int, char*) { } template<typename T> void detector<T>::power_down() { } template<typename T> int detector<T>::power_scan() {return 0;} /*xx厂家传感器*/ template<typename T> void detector<T>::sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } template<typename T> void detector<T>::danger_warn() { } template<typename T> void detector<T>::dev_state() {} /*----------------------------------------------------------------------------*/ /*yy厂家传感器*/ struct detector_a:detector<detector_a> { /*void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 }*/ }; #endif //main.cpp #include"detector.h" int main (void) { __enable_irq(); detector<detector_a> co_star; co_star.fun(); while(1) { } } 为了方便阅读,我删除了函数中具体的内容,只留下了一个最小框架。 复制detector<detector_a> co_star; co_star.fun(); 主函数中实例化了一个探测器co_star模板类,并且参数指向了detector模板的派生类detector_a, 由于我们使用的传感器类型较多,每个厂家,每个型号 的传感器的工作方式又可能不尽相同。 所以我在detector模板中预留了一种传感器(xx厂家的传感器),其扫描方式为detector<T>::sensor_scan()。 其后因市场原因,又需要使用yy厂家的传感器,所以我在detector模板的基础上派生了一个detector_a类, 同样定义yy的扫描方式为sensor_scan(),只是在detector实例化的时候,将参数指向了detector_a . 复制/*yy厂家传感器*/ struct detector_a:detector<detector_a>{ void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } 所以主函数中co_star.fun()调用的detector<detector_a>::sensor_scan()其实是指向了yy厂家传感器的扫描方式 detector_a::sensor_scan()。 这里不仅仅传感器扫描可以通过CRTP来拓展,从fun() 到 detector_poll() 到 sensor_scan() 全都可以通过CRTP的静态多态效应来拓展/重构。 复制struct detector_a:detector<detector_a>{ void fun() { ... } struct detector_a:detector<detector_a>{ void detector_poll() { ... } 从整个框架到一个内部函数都可用这种机制来拓展/重构,其可拓展的粒度可以是一个最小的函数调用。现在你可否体会到C++ CRTP模式的程序拓展呢? 本帖测试源代码也上传至此,具体的函数实现被我删掉了,仅以一个io翻转来做演示,请见谅。 如果您还想深入了解CRTP框架的嵌入式软件设计,可以看看john_lee老师的课程记录 https://bbs.21ic.com/icview-577248-1-1.html
//detector.h #ifndef __Detector_H__ #define __Detector_H__ #include "routine.h" template<typename T> struct detector { void fun() { static_cast<T*>(this)->detector_init(0,"__DATE__"); for(;;){ static_cast<T*>(this)->detector_poll(); static_cast<T*>(this)->power_down(); } } void detector_poll() { while( static_cast<T*>(this)->power_scan() ); static_cast<T*>(this)->sensor_scan(); static_cast<T*>(this)->danger_warn(); static_cast<T*>(this)->dev_state(); } void detector_init(int, char*); int power_scan(); void power_down(); void danger_warn(); void dev_state(); void sensor_scan(); }; template<typename T> void detector<T>::detector_init(int, char*) { } template<typename T> void detector<T>::power_down() { } template<typename T> int detector<T>::power_scan() {return 0;} /*xx厂家传感器*/ template<typename T> void detector<T>::sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } template<typename T> void detector<T>::danger_warn() { } template<typename T> void detector<T>::dev_state() {} /*----------------------------------------------------------------------------*/ /*yy厂家传感器*/ struct detector_a:detector<detector_a> { /*void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 }*/ }; #endif //main.cpp #include"detector.h" int main (void) { __enable_irq(); detector<detector_a> co_star; co_star.fun(); while(1) { } } 为了方便阅读,我删除了函数中具体的内容,只留下了一个最小框架。 复制detector<detector_a> co_star; co_star.fun(); 主函数中实例化了一个探测器co_star模板类,并且参数指向了detector模板的派生类detector_a, 由于我们使用的传感器类型较多,每个厂家,每个型号 的传感器的工作方式又可能不尽相同。 所以我在detector模板中预留了一种传感器(xx厂家的传感器),其扫描方式为detector<T>::sensor_scan()。 其后因市场原因,又需要使用yy厂家的传感器,所以我在detector模板的基础上派生了一个detector_a类, 同样定义yy的扫描方式为sensor_scan(),只是在detector实例化的时候,将参数指向了detector_a . 复制/*yy厂家传感器*/ struct detector_a:detector<detector_a>{ void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } 所以主函数中co_star.fun()调用的detector<detector_a>::sensor_scan()其实是指向了yy厂家传感器的扫描方式 detector_a::sensor_scan()。 这里不仅仅传感器扫描可以通过CRTP来拓展,从fun() 到 detector_poll() 到 sensor_scan() 全都可以通过CRTP的静态多态效应来拓展/重构。 复制struct detector_a:detector<detector_a>{ void fun() { ... } struct detector_a:detector<detector_a>{ void detector_poll() { ... } 从整个框架到一个内部函数都可用这种机制来拓展/重构,其可拓展的粒度可以是一个最小的函数调用。现在你可否体会到C++ CRTP模式的程序拓展呢? 本帖测试源代码也上传至此,具体的函数实现被我删掉了,仅以一个io翻转来做演示,请见谅。 如果您还想深入了解CRTP框架的嵌入式软件设计,可以看看john_lee老师的课程记录 https://bbs.21ic.com/icview-577248-1-1.html
detector<detector_a> co_star; co_star.fun(); 主函数中实例化了一个探测器co_star模板类,并且参数指向了detector模板的派生类detector_a, 由于我们使用的传感器类型较多,每个厂家,每个型号 的传感器的工作方式又可能不尽相同。 所以我在detector模板中预留了一种传感器(xx厂家的传感器),其扫描方式为detector<T>::sensor_scan()。 其后因市场原因,又需要使用yy厂家的传感器,所以我在detector模板的基础上派生了一个detector_a类, 同样定义yy的扫描方式为sensor_scan(),只是在detector实例化的时候,将参数指向了detector_a . 复制/*yy厂家传感器*/ struct detector_a:detector<detector_a>{ void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } 所以主函数中co_star.fun()调用的detector<detector_a>::sensor_scan()其实是指向了yy厂家传感器的扫描方式 detector_a::sensor_scan()。 这里不仅仅传感器扫描可以通过CRTP来拓展,从fun() 到 detector_poll() 到 sensor_scan() 全都可以通过CRTP的静态多态效应来拓展/重构。 复制struct detector_a:detector<detector_a>{ void fun() { ... } struct detector_a:detector<detector_a>{ void detector_poll() { ... } 从整个框架到一个内部函数都可用这种机制来拓展/重构,其可拓展的粒度可以是一个最小的函数调用。现在你可否体会到C++ CRTP模式的程序拓展呢? 本帖测试源代码也上传至此,具体的函数实现被我删掉了,仅以一个io翻转来做演示,请见谅。 如果您还想深入了解CRTP框架的嵌入式软件设计,可以看看john_lee老师的课程记录 https://bbs.21ic.com/icview-577248-1-1.html
/*yy厂家传感器*/ struct detector_a:detector<detector_a>{ void sensor_scan() { routine_tt.io();//传感器扫描用翻转io来指示 } 所以主函数中co_star.fun()调用的detector<detector_a>::sensor_scan()其实是指向了yy厂家传感器的扫描方式 detector_a::sensor_scan()。 这里不仅仅传感器扫描可以通过CRTP来拓展,从fun() 到 detector_poll() 到 sensor_scan() 全都可以通过CRTP的静态多态效应来拓展/重构。 复制struct detector_a:detector<detector_a>{ void fun() { ... } struct detector_a:detector<detector_a>{ void detector_poll() { ... } 从整个框架到一个内部函数都可用这种机制来拓展/重构,其可拓展的粒度可以是一个最小的函数调用。现在你可否体会到C++ CRTP模式的程序拓展呢? 本帖测试源代码也上传至此,具体的函数实现被我删掉了,仅以一个io翻转来做演示,请见谅。 如果您还想深入了解CRTP框架的嵌入式软件设计,可以看看john_lee老师的课程记录 https://bbs.21ic.com/icview-577248-1-1.html
struct detector_a:detector<detector_a>{ void fun() { ... } struct detector_a:detector<detector_a>{ void detector_poll() { ... } 从整个框架到一个内部函数都可用这种机制来拓展/重构,其可拓展的粒度可以是一个最小的函数调用。现在你可否体会到C++ CRTP模式的程序拓展呢? 本帖测试源代码也上传至此,具体的函数实现被我删掉了,仅以一个io翻转来做演示,请见谅。 如果您还想深入了解CRTP框架的嵌入式软件设计,可以看看john_lee老师的课程记录 https://bbs.21ic.com/icview-577248-1-1.html
您需要 登录 才可以下载或查看,没有账号?注册
收藏0 举报
查看全部评分
airwill 发表于 2013-8-28 06:26 非常支持。 看来c++ 进入嵌入式系统,也具有很强的优势。 很想找时间也来玩一玩 ...
本版积分规则 发表回复 回帖并转播 回帖后跳转到最后一页
等级类勋章
发帖类勋章
时间类勋章
人才类勋章
43
5073
22
扫码关注 21ic 官方微信
扫码关注嵌入式微处理器
扫码关注电源系统设计
扫码关注21ic项目外包
扫码浏览21ic手机版
本站介绍 | 申请友情链接 | 欢迎投稿 | 隐私声明 | 广告业务 | 网站地图 | 联系我们 | 诚聘英才
京公网安备 11010802024343号