打印

基于C++简易CRTP框架的嵌入式软件设计

[复制链接]
3277|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dong_abc|  楼主 | 2013-8-27 21:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 dong_abc 于 2014-5-13 13:18 编辑

题记:有一条小径,它别有洞天 !

         近段时间在学习C++模板元编程。在学习C++ CRTP(递归模板)的时候,发现我只能用两个字来形容CRTP这种编程框架——“自由”,程序随性自由拓展,而丝毫不用改变之前原有的代码结构。
         
        1、 首先,简单描述一下C++的CRTP编程模式的使用。
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翻转来做演示,请见谅。
NUC120CppDemo.rar (231.12 KB)

如果您还想深入了解CRTP框架的嵌入式软件设计,可以看看john_lee老师的课程记录
https://bbs.21ic.com/icview-577248-1-1.html
评分
参与人数 1威望 +4 收起 理由
john_lee + 4 很给力!

相关帖子

沙发
airwill| | 2013-8-28 06:26 | 只看该作者
非常支持。
看来c++ 进入嵌入式系统,也具有很强的优势。
很想找时间也来玩一玩

使用特权

评论回复
板凳
diweo| | 2013-8-28 08:04 | 只看该作者
确实很有吸引力

使用特权

评论回复
地板
dong_abc|  楼主 | 2013-8-28 12:35 | 只看该作者
airwill 发表于 2013-8-28 06:26
非常支持。
看来c++ 进入嵌入式系统,也具有很强的优势。
很想找时间也来玩一玩 ...

恩,舍得花时间玩的人不多。
后续我还会发一些关于元编程的嵌入式应用。

使用特权

评论回复
5
dong_abc|  楼主 | 2013-8-28 12:45 | 只看该作者
本帖最后由 dong_abc 于 2014-5-13 12:04 编辑

元编程与传统编程方法完全不一样。元程序是在编译的时候解析,通过摸板实例化来组合生成程序代码,其性能丝毫不比C代码差!

使用特权

评论回复
6
dong_abc|  楼主 | 2013-8-28 21:24 | 只看该作者
本帖最后由 dong_abc 于 2014-5-13 13:19 编辑

C++ CRTP ...... !
......

使用特权

评论回复
7
sedatefire| | 2013-8-31 22:09 | 只看该作者
lua,不知大家有何看法?

使用特权

评论回复
评论
dong_abc 2013-11-2 19:19 回复TA
好像是个脚本相关的,没接触过。 
8
dirtwillfly| | 2013-9-1 08:17 | 只看该作者
没玩过,关注下。难道以后嵌入式开发也逐渐由C发展到C++

使用特权

评论回复
9
xd54622| | 2013-9-2 19:29 | 只看该作者
关注一下

使用特权

评论回复
10
dong_abc|  楼主 | 2013-11-2 17:02 | 只看该作者
话说CRTP应该算是我目前所见过建设代码架构最好的方式之一 --------简洁、灵活、高效。

使用特权

评论回复
11
dong_abc|  楼主 | 2013-11-4 12:38 | 只看该作者
接上:
最重要的是它不依赖任何第三方组件。

使用特权

评论回复
12
限量_个性。| | 2013-11-4 13:09 | 只看该作者
最近也在C++,跟楼楼后面学两招~~:lol:lol

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:此id已冬眠...

43

主题

5078

帖子

22

粉丝