1. 周立功
    +关注
    关注 28
    文章 122
    浏览量 18826
  2. 虚函数
    +关注
    关注 0
    文章 2
    浏览量 255
  3. 抽象类
    +关注
    关注 0
    文章 1
    浏览量 291

开发中虚函数应用,大大减少开发时间

周立功单片机 2017-10-12 09:30 次阅读
近日周立功教授公开了数年的心血之作《程序设计与数据结构》,电子版已无偿性分享到电子工程师与高校群体下载,经周立功教授授权,特对本书内容进行连载。 >>>> 1.1 虚函数 >>> 1.1.1 二叉树 树的应用非常广泛,比如,数据库就是由树构造而成的,C编译器的词法分析器也是经过语法分析生成的树。 树是一种管理象树干、树枝、树叶一样关系的数据的数据结构,通常一棵树由根部长出一个树干,接着从树干长出一些树枝,然后树枝上又长出更小的树枝,而叶子则长在最细的树枝上,树这种数据结构正是象一棵树倒过来的树木。 树是由结点(顶点)和枝构成的,由一个结点作为起点,这个起点称为树的根结点。从根结点上可以连出几条枝,每条枝都和一个结点相连,延伸出来的这些结点又可以继续通过枝延伸出新的结点。这个过程中的旧结点称作父结点,而延伸出来的新结点称作子结点,一个子结点都没有的结点就叫做叶子结点。另外,从根结点出发到达某个结点所要经过的枝的个数叫做这个结点的深度。 从家谱树血缘关系来看,家谱树使得介绍计算机科学中用于描述树结构的术语变得更简单了。树中的每一个结点都可以有几个孩子,但是只有一个双亲。在树中祖先和孙子的意义与日常语言中的意义完全相同。 与根形成对比的是没有孩子的结点,这些结点称为叶,而既不是根又不是叶的结点称为内部结点,树的长度定义为从根到叶的最长路径的长度(或深度)。在一颗树里,如果从根到叶的每条路径的长度都大致相等,那么这颗树被称为平衡树。实际上,要实现某种永远能够保证平衡的树是很复杂的,这也是为什么存在多种不同种类的树的原因。 实际上,在树的每一层次都是分叉形式,如果任意选取树中的一个结点和它的子树,所得到的部分都符合树的定义。树中的每个结点都可以看成是以它自己为根的子树的根,这就是树结构的递归特性。如果以递归的观点考察树,那么树只是一个结点和一个附着其上的子树的集合——在叶结点的情景下该集合为空,因此树的递归特性是其底层表示和大部分针对树操作的算法的基础。 树的一个重要的子类是二叉树,二叉树是一种常用的树形数据结构。二叉树的每个结点最多只有两个子结点(left和right),且除了根以外的其它结点,要么是双亲结点的左孩子,要么是右孩子。 >>> 1.1.2 表达式算术树 1. 问题 求解算术表达式就是一种二叉树,它的结点包含两种类型的对象:操作符和终值。操作符是拥有操作数的对象,终值是没有操作数的对象。表达式树背后的思想——存储在父结点中的是操作符,其操作数是由子结点延伸的子树组成的。操作数有可能是终值,或它们本身也可能是其它的表达式。表达式在子树中展开,终值驻留在叶子结点中,这种组织形式的好处是可以通过表达式将一个表达式转换为3种常见的表示形式:前缀、中缀和后缀,但中缀表达式是在数学中学到的最为熟悉的表达方式。在这里,将以2*(3+4)+5中缀表达式算术树结构为例。 首先将“2*(3+4)+5”拆分为左子树和右子树其中,“+” 为根节点左子树的值为2*(3+4),右子树的值为5;接着将2*(3+4)拆分为左子树和右子树,其中,“*”为根节点,左子树的值为2,右子树的值为3+4;然后将3+4拆分为左子树和右子树,其中,“+”为根节点,左子树的值为3,右子树的值为4,详见 4.6。注意,树的表示法中不需要任何小括号或运算符优先级的知识,因为它描述的计算过程是唯一的。 图 4.6 表达式算术树 由此可见从根结点(Node)到叶进行分析该表达式算术树的结点是算术运算符“+(Additive)”“*(Multiplicative)”,它的树叶是操作数(Number)。由于这里所有的操作都是二元(Binary)的,即每个结点最多只有两个孩子,这颗特定的树正好是二叉树。因此可以用以下方式计算(calculate,简写为calc)每个结点: ● 如果是一个数字,则返回它的值; ● 如果是一个运算符,则计算左子树和右子树的值。 其计算过程是先分别输入3和4,接着计算3+4;然后输入2,再接着计算2*(3+4);接着输入5,最后计算2*(3+4)+5。 传统的做法是定义一个struct _Node,包含二元运算符和数字结点,详见程序清单 4.12 程序清单 4.12 表达式算术树接口(calctree.h) 1    #pragma once  2 3    #define NUM_NODE    1  4    #define ADD_NODE     2  5    #define MULT_NODE  3 6 7    typedef struct _Node{ 8         int type; 9         double val; 10        struct _Node *pLeft;  11        struct _Node *pRight;  12  }Node;  13 14  double Calc(Node * pNode);  15 16  #define newNumNode(val) {NUM_NODE, (val), NULL, NULL};  17  #define newAddNode(pLeft, pRight) {ADD_NODE, 0, (pLeft), (pRight)};  18  #define newMultNode(pLeft, pRight) {MULT_NODE, 0 , (pLeft), (pRight)};  其中,使用了名为newNumNode、newAddNode和newMultNode的宏将结构体初始化,表达式算术树接口的实现详见程序清单 4.13 程序清单 4.13 表达式算术树接口的实现(cacltree.c) 1    #include"Node.h"  2 3    double Calc(Node * pNode) 4    {  5         double x = 0;  6         switch (pNode -> type){  7         case NUM_NODE: 8               x = pNode -> val; 9               break;  10        case ADD_NODE: 11             x = Calc(pNode -> pLeft) + Calc(pNode -> pRight);  12             break;  13        case MULT_NODE:  14             x = Calc(pNode -> pLeft) * Calc(pNode -> pRight); 15             break;  16        default: 17             break; 18        }  19        return x; 20  } 表达式算术树的使用范例详见程序清单 4.14 程序清单 4.14 表达式算术树使用范例 1    #include <stdio.h> 2    #include "Node.h" 3 4    void main()  5    { 6         Node node1 = newNumNode(20.0); 7         Node node2 = newNumNode(-10.0); 8         Node node3 = newAddNode(&node1, &node2); 9         Node node4 = newNumNode(0.1); 10        Node node5 = newMultNode(&node3, &node4); 11        printf("Calculating the tree\n");  12        double x = Calc(&node5);  13        printf("Result:%lf\n", x);  14  }  2. 抽象类 根据问题的描述,需求词汇表中有一组这样的概念,比如,根结点和左右叶子结点的操作数,且加法和乘法都是二元操作。虽然词汇表对应的词汇为Node、_pLeft、_pRight、Number、Binary、Additive和Multiplicative,但用Node、_pLeft、_pRight、NumNode、BinNode、AddNode和MultNode描述表达式算术树的各个结点更准确。 由于AddNode和MultNode都是二元操作,其共性是两个数(_pLeft和_pRight)的计算,其可变性分别为加法和乘法,因此可以将它们的共性包含在BinNode中,可变性分别包含在AddNode和MultNode中。 其实输入操作数同样可以视为计算,因此NumNode和BinNode的共性也是计算,不妨将它们的共性上移到Node抽象类中。 显然,基于面向对象的C编程,则表达式算术树的所有结点都是从类Node继承的子类,Node的直系后代为NumNode和BinNode,NumNode表示一个数,BinNode表示一个二元运算,然后再从BinNode派生两个类:AddNode和MultNode。 图 4.7所示展示了类的层次性,它们是一种“is-a”的抽象层次结构,子类AddNode和MultNode重新定义了BinNode和Node基类的结构和行为。基类代表了一般化的抽象,子类代表了特殊的抽象。虽然抽象类Node或BinNode不能实例化,只能作为其它类的父类,但NumNode、AddNode和MultNode子类是可以实例化的。 图 4.7 结点的类层次 Node抽象类的定义如下: 1    typedef struct _Node{  2         double (*nodeCalc)(struct _Node *pThis);  3    }Node;  除了Node之外,每个子类都要实现自己的nodeCalc计算方法,并返回一个作为计算结点值的双精度数。即: 1    typedef struct _NumNode{  2          Node       isa;  3          double     _num; 4    }NumNode; 5 6    typedef struct _BinNode{ 7          Node     isa;  8          Node  *_pLeft;  9          Node  *_pRight; 10  }BinNode; 11 12  typedef struct _AddNode{  13        BinNode   isa;  14  }AddNode;  15 16  typedef struct _MultNode{ 17        BinNode   isa; 18  }MultNode; 其中的NumNode结点是从Node分出来的,_num表示数值。BinNode也是从Node分出来的,_pLeft和_pRight分别为指向左子树和右子树的指针,而AddNode和MultNode又是从BinNode分出来的。 此前,针对继承和多态框架,使用了一种称为静态的初始化范型。在这里,将使用动态内存分配初始化范型处理继承和多态框架。 3.建立接口 由于对象不同,因此动态分配内存的方式不一样,但其共性是——不再使用某个对象时,释放动态内存的方法是一样,因此还需要添加一个node_cleanup()函数,这是通过free()实现的,详见程序清单 4.15 程序清单 4.15 表达式算术树的接口(CalcTree1.h) 1    #pragma once 2    typedef struct _Node Node; 3    typedef double (*node_calc_t)(Node *pThis); 4    typedef void (*node_cleanup_t)(Node *pThis);  5    struct _Node{ 6          node_calc_t    node_calc; 7          node_cleanup_t    node_cleanup;  8    }; 9 10  typedef struct _NumNode{ 11        Node       isa;  12        double     _num;  13  }NumNode; 14 15  typedef struct _BinNode{ 16        Node        isa;  17        Node       *_pLeft; 18        Node       *_pRight;  19  }BinNode; 20 21  typedef struct _AddNode{ 22        BinNode   isa;  23  }AddNode; 24 25  typedef struct _MultNode{  26        BinNode   isa;  27  }MultNode;  28 29  NumNode * newNumNode(double num);  30  double node_calc(Node *pThis); 31  AddNode * newAddNode(Node *pLeft, Node *pRight);  32  MultNode * newMultNode(Node *pLeft, Node *pRight);  33  void node_cleanup(Node *pThis); 实现表达式算术树的第一步是输入数据和初始化NumNode结构体的变量isa和_num,newNumNode()函数原型如下: NumNode * newNumNode(double num);  其调用形式如下: Node * pNode1 = (Node *)newNumNode(20.0);  Node * pNode2 = (Node *)newNumNode(-10.0); 接下来开始为计算做准备,node_calc()函数原型如下: double node_calc(Node *pThis); 其调用形式如下: node_calc(pNode1); 然后开始进行加法运算,newAddNode()函数原型如下: AddNode * newAddNode(Node *pLeft, Node *pRight);  其调用形式如下: Node * pNode3 = (Node *)newAddNode(pNode1, pNode2); 当然,也可以开始进行乘法运算了,newMultNode()函数原型如下: MultNode * newMultNode(Node *pLeft, Node *pRight);  其调用形式如下: Node * pNode4 = (Node *)newNumNode(0.1); Node * pNode5 = (Node *)newMultNode(pNode3, pNode4);  一切准备就绪,则计算最终结果并释放不再使用的资源,node_cleanup()函数原型如下: void node_cleanup(Node *pThis); 其调用形式如下: printf("Calculating the tree\n");   double x = node_calc(pNode5); printf("Result:%lf\n", x);  node_cleanup(pNode5); 4. 实现接口 显然,为每个结点创建了相应的类后,就可以为每个结点创建一个动态变量,即可在运行时根据需要使用malloc()分配内存并使用指针存储该地址,并使用指针初始化结构体的各个成员,CalcTree1.c接口的实现详见程序清单 4.16 程序清单 4.16表达式算术树接口的实现(CalcTree1.c) 1    #include <stdio.h> 2    #include <malloc.h>  3    #include " CalcTree1.h "  4 5    NumNode * newNumNode(double num)  6    {  7          NumNode *pNumNode = malloc(sizeof(NumNode)); 8         if(pNumNode != NULL){ 9               pNumNode -> isa.node_calc = _numnode_calc; 10              pNumNode -> isa.node_cleanup = _numnode_cleanup;  11              pNumNode -> _num = num; 12        }  13        return pNumNode; 14  }  15 16  static double _numnode_calc(Node *pThis)  17  {  18        printf("numeric node %lf\n", ((NumNode *) pThis) -> _num);  19        return ((NumNode *)pThis) -> _num;  20  }  21 22  static void _numnode_cleanup(Node *pThis) 23  { 24        printf("NumNode cleanup\n"); 25        free(pThis);  26  } 27 28  double node_calc(Node *pThis)  29  { 30        return pThis -> node_calc(pThis); 31  } 32 33  AddNode * newAddNode(Node *pLeft, Node *pRight) 34  { 35        AddNode *pAddNode = malloc(sizeof(AddNode));  36        if(pAddNode != NULL){  37              pAddNode -> isa.isa.node_calc =_addnode_calc; 38              pAddNode -> isa.isa.node_cleanup = _binnode_cleanup;  39              pAddNode -> isa._pLeft = pLeft;  40              pAddNode -> isa._pRight = pRight;  41        } 42        return pAddNode; 43  }  44 45  static double _addnode_calc(Node *pThis)  46  {  47        printf("Adding...\n");  48        AddNode * pAddNode = (AddNode*)pThis; 49        return node_calc(pAddNode -> isa._pLeft) + node_calc(pAddNode -> isa._pRight);  50  } 51 52  static double _multnode_calc(Node *pThis) 53  { 54        printf("Multiplying...\n");  55        MultNode * pMultNode = (MultNode*)pThis;  56        return node_calc(pMultNode -> isa._pLeft)*node_calc(pMultNode -> isa._pRight);  57  } 58 59  static void _binnode_cleanup(Node *pThis)  60  {  61        printf("BinNode cleanup\n"); 62        BinNode * pBinNode = (BinNode*)pThis;  63        node_cleanup(pBinNode ->_pLeft); 64        node_cleanup(pBinNode ->_pRight); 65        free(pThis); 66  }  67 68  MultNode * newMultNode(Node *pLeft, Node *pRight) 69  {  70        MultNode *pMultNode = malloc(sizeof(MultNode)); 71        if(pMultNode != NULL){  72              pMultNode -> isa.isa.node_calc = _multnode_calc;  73              pMultNode -> isa.isa.node_cleanup = _binnode_cleanup; 74              pMultNode -> isa._pLeft = pLeft;  75              pMultNode -> isa._pRight = pRight;  76        } 77        return pMultNode; 78  }  79 80  void node_cleanup(Node *pThis) 81  { 82        pThis -> node_cleanup(pThis);  83  } >>> 1.1.3 虚函数 虽然可以使用继承实现表达式算术树,但实现代码中的每个对象都有函数指针。如果结构体内有很多函数指针,或必须生成更多的对象时,将会出现多个对象具有相同的行为、需要较多的函数指针和需要生成较多数量的对象,将会浪费很多的内存。 不妨将Node中的成员转移到另一个结构体中实现一个虚函数表,然后在接口中创建一个抽象数据类型NodeVTable,在此基础上定义一个指向该表的指针vtable。比如: 1    // 接口(CalcTree2.h) 2    typedef  struct _NodeVTable  NodeVTable; 3    typedef struct _Node{ 4         const NodeVTable * vtable;  5    }Node; 6    // 实现(CalcTree2.c) 7    typedef double (*node_calc_t)(Node *pThis); 8    typedef void (*node_cleanup_t)(Node *pThis);  9    struct _NodeVTable{  10        const node_calc_t node_calc; 11        const node_cleanup_t node_cleanup;  12  };  13  const NodeVTable _addnode_vtable = { _addnode_calc, _binnode_cleanup};  表达式算术树的接口详见程序清单 4.17,其中的NumNode派生于Node,_num表示数值;BinNode也是派生于Node,pLeft和pRight分别表示指向左子树和右子树的指针;而AddNode和MultNode又派生于BinNode。虽然抽象类包含一个或多个纯虚函数类,但不能实例化(此类没有对象可创建),只有从一个抽象类派生的类和为所有纯虚函数提供了实现代码的类才能实例化,它们都必须提供自己的计算方法node_calc和node_cleanup。 程序清单 4.17 表达式算术树接口(CalcTree2.h) 1    #pragma once  2 3    typedef  struct _NodeVTable  NodeVTable; 4    typedef struct _Node{  5         const NodeVTable * vtable; 6    }Node; 7 8    typedef struct _NumNode{  9         Node   isa;  10        double  _num;  11  }NumNode;  12 13  typedef struct _AddNode{  14        Node  isa; 15        Node  *_pLeft; 16        Node  *_pRight;  17  }AddNode; 18 19  typedef struct _MultNode{  20        Node  isa;  21        Node  *_pLeft; 22        Node  *_pRight; 23  }MultNode; 24 25  double node_calc(Node *pThis);  26  void node_cleanup(Node *pThis);  27 28  NumNode * newNumNode(double num); 29  AddNode * newAddNode(Node *pLeft, Node *pRight);  30  MultNode * newMultNode(Node *pLeft, Node *pRight);  显然,为每个结点创建了相应的类后,就可以为每个结点创建一个动态变量,即可在运行时根据需要使用malloc()分配内存并使用指针存储该地址,并使用指针初始化结构体的各个成员,表达式算术树接口的实现详见程序清单 4.18 程序清单 4.18 表达式算术树接口的实现(CalcTree2.c) 1    #include <stdio.h> 2    #include <malloc.h> 3    #include " CalcTree2.h " 5    typedef double (*node_calc_t)(Node *pThis); 6    typedef void (*node_cleanup_t)(Node *pThis); 7    struct _NodeVTable{ 8          const node_calc_t node_calc; 9          const node_cleanup_t node_cleanup; 10  }; 11 12  static double _numnode_calc(Node *pThis) 13  { 14        printf("numeric node %lf\n", ((NumNode *)pThis)->_num); 15        return ((NumNode *)pThis) ->_num; 16  } 17 18  static void _numnode_cleanup(Node *pThis) 19  { 20        printf("NumNode cleanup\n"); 21        free(pThis); 22  } 23 24  const NodeVTable _numnode_vtable = {_numnode_calc, _numnode_cleanup}; 25 26  static void _binnode_cleanup(Node *pThis) 27  { 28        printf("BinNode cleanup\n"); 29        BinNode * pBinNode = (BinNode*)pThis; 30        node_cleanup(pBinNode ->_pLeft); 31        node_cleanup(pBinNode ->_pRight); 32        free(pThis); 33  }  34 35  static double _addnode_calc(Node *pThis) 36  { 37        printf("Adding...\n"); 38        AddNode * pAddNode = (AddNode*)pThis; 39        return node_calc(pAddNode -> isa._pLeft) + node_calc(pAddNode -> isa._pRight); 40  } 41 42  const NodeVTable _addnode_vtable = { _addnode_calc, _binnode_cleanup }; 43 44  static double _multnode_calc(Node *pThis) 45  { 46        printf("Multiplying...\n"); 47        MultNode * pMultNode = (MultNode*)pThis; 48        return node_calc(pMultNode -> isa._pLeft)*node_calc(pMultNode -> isa._pRight); 49  } 50  51  const NodeVTable _multnode_vtable = { _multnode_calc, _binnode_cleanup }; 52 53  NumNode * newNumNode(double num)  54  { 55        NumNode *pNumNode  = malloc(sizeof(NumNode)); 56        if(pNumNode != NULL){ 57              pNumNode -> isa.vtable  = &_numnode_vtable; 58              pNumNode -> _num         = num;  59        }  60        return pNumNode; 60        return pNumNode;  61  }  62 63  AddNode * newAddNode(Node *pLeft, Node *pRight)  64  { 65        AddNode *pAddNode  = malloc(sizeof(AddNode));  66        if(pAddNode != NULL){  67              pAddNode -> isa.isa.vtable   = &_addnode_vtable; 68              pAddNode -> isa._pLeft  = pLeft; 69              pAddNode -> isa._pRight      = pRight; 70        }  71        return pAddNode; 72  } 73 74  MultNode * newMultNode(Node *pLeft, Node *pRight) 75  {  76        MultNode *pMultNode = malloc(sizeof(MultNode)); 77        if(pMultNode != NULL){ 78              pMultNode -> isa.isa.vtable   = &_multnode_vtable; 79              pMultNode -> isa._pLeft  = pLeft; 80              pMultNode -> isa._pRight  = pRight; 81        }  82        return pMultNode; 83  }  84 85  double node_calc(Node *pThis) 86  { 87        return pThis -> vtable -> node_calc(pThis); 88  }  89 90  void node_cleanup(Node *pThis)  92        pThis -> vtable -> node_cleanup(pThis);  93  }

热门推荐

  1. 电子书 电源开关设计秘笈 第2部
  2. 如何构建高效NFC设计以支持各种应用(附代码)
  3. 【干货】全自动AI移动机器人开源资料
  4. 电子书 中美人工智能行业生态比较
  5. 电子书 电源开关设计秘笈 第一部
原文标题:周立功:虚函数,帮你节约更多内存 文章出处:【微信号:Zlgmcu7890,微信公众号:周立功单片机】欢迎添加关注!文章转载请注明出处。
收藏 人收藏
分享:

评论

相关推荐

带看门狗功能的专用复位芯片设计方案

在产品规划中,如使用芯片内部集成的DCDC模块给系统的各个子模块(如内存、电子硬盘、硬件看门狗等)供....
的头像 周立功单片机 发表于 06-13 09:16 549次 阅读
带看门狗功能的专用复位芯片设计方案

AWorks软件设计,邮箱、消息队列和自旋锁使用方法

本文介绍了邮箱、消息队列和自旋锁的使用方法。信号量只能用于任务间的同步,不能传递更多的信息,为此,A....
的头像 ZLG致远电子 发表于 06-13 09:13 897次 阅读
AWorks软件设计,邮箱、消息队列和自旋锁使用方法

面向AWorks框架管理文件的方法和数据结构

文件系统是在存储设备中(SD Card、NAND Flash…)组织文件的方法和数据结构,用于管理文....
的头像 ZLG致远电子 发表于 06-05 09:18 757次 阅读
面向AWorks框架管理文件的方法和数据结构

一个高集成度的掉电检测电路应用

对于核心板的嵌入式系统来说,异常掉电情况下数据不丢失,稳定性是根本。本文基于CAT706介绍一种能够....
的头像 周立功单片机 发表于 05-25 09:35 1895次 阅读
一个高集成度的掉电检测电路应用

AWorks对常见的外部通用设备接口应用

AWorks对常用的硬件设备(LED、按键、蜂鸣器、数码管等等)进行了抽象,分别为每一类设备提供了通....
的头像 周立功单片机 发表于 05-24 09:44 1242次 阅读
AWorks对常见的外部通用设备接口应用

M105x系列跨界硬件核心板嵌入式开发

迄今为止,知道AWorks的开发者越来越多,却只有极少数了解其精髓,在即将发布之际,周立功教授及其团....
的头像 周立功单片机 发表于 05-23 09:18 1338次 阅读
M105x系列跨界硬件核心板嵌入式开发

全新的物联网操作系统AWorks IoT OS

Wi-Fi、zigbee、NFC、LoRa等无线技术使用得十分广泛,但无线电路设计存在诸多难点:天线....
的头像 ZLG致远电子 发表于 05-22 08:57 2574次 阅读
全新的物联网操作系统AWorks IoT OS

i.MX28x系列无线工控板中的IoT-A28LI主板整体布局

基于AWorks平台的ARM9与Cortex-A系列工控主板,具有丰富的扩展接口,可以扩展zigbe....
的头像 ZLG致远电子 发表于 05-19 08:56 1148次 阅读
i.MX28x系列无线工控板中的IoT-A28LI主板整体布局

基于AWorks平台A3352系列无线核心板设计方案

基于AWorks平台的A6G2C(Cortex-A7内核)与A3352(Cortex-A8内核)系列....
的头像 ZLG致远电子 发表于 05-18 08:56 918次 阅读
基于AWorks平台A3352系列无线核心板设计方案

M3352核心板及评估底板及产品设计框图

为了便于用户快速开发产品,ZLG致远电子研发设计了基于AWorks平台的,集MCU、DDR3、Nan....
的头像 周立功单片机 发表于 05-16 09:09 1516次 阅读
M3352核心板及评估底板及产品设计框图

集MCU、DDR、NandFlash、硬件看门狗等等于一体核心板

为了便于用户快速开发产品,ZLG致远电子研发设计了基于AWorks平台的,集MCU、DDR、Nand....
的头像 周立功单片机 发表于 05-15 09:15 1368次 阅读
集MCU、DDR、NandFlash、硬件看门狗等等于一体核心板

AWorks开发者越来越多,却只有极少数了解其精髓

迄今为止,知道AWorks的开发者越来越多,却只有极少数了解其精髓,在即将发布之际,周立功教授撰写了....
的头像 ZLG致远电子 发表于 05-07 08:34 1987次 阅读
AWorks开发者越来越多,却只有极少数了解其精髓

周立功的AWorks哲学思想

苹果之所以成为全球最赚钱的公司,关键在于产品的性能超越了用户的预期,且因为大量可重用的核心领域知识,....
的头像 人间烟火123 发表于 05-04 14:38 1729次 阅读
周立功的AWorks哲学思想

基于Ametal平台开发,快速完成开发设计!

传统旋钮采用机械式结构,面板上需要开孔,长时间使用易磨损、进灰尘等,采用新型吸附式磁旋钮可以轻松解决....
的头像 周立功单片机 发表于 05-04 09:11 1702次 阅读
基于Ametal平台开发,快速完成开发设计!

隔离电源自主搭建VS模块方案设计

电源是电子系统的心脏,工业应用中,为系统前级或接口供电的电源一般都要求有高的抗干扰性能,各种隔离型的....
的头像 ZLG致远电子 发表于 04-27 08:46 1926次 阅读
隔离电源自主搭建VS模块方案设计

容量Flash器件编程设计,体验极速高效的全新烧录感受!

它拥有极致速度、高效压杆;它自带独立操作系统,省去PC机方便产线部署;它拥有独特的母片分析”“文件分....
的头像 周立功单片机 发表于 04-24 08:42 1825次 阅读
容量Flash器件编程设计,体验极速高效的全新烧录感受!

隔离反激和非隔离BUCK应用设计方案

在产品设计时,倘若没有考虑应用环境对电源隔离的要求,产品到了应用时就会出现因设计方案的不当导致的系统....
的头像 周立功单片机 发表于 04-13 08:35 2239次 阅读
隔离反激和非隔离BUCK应用设计方案

滤芯防伪技术,可以分布式读取8处防伪标签

空气净化器、净水器市场发展迅猛,很多品牌商都抢占到了自己的份额。但在实际使用过程中却发现很多用户长期....
的头像 周立功单片机 发表于 03-28 08:29 1251次 阅读
滤芯防伪技术,可以分布式读取8处防伪标签

一款跨界核心板,让物联网设计如MCU系统便捷

M1052跨界核心板让设计者如开发普通MCU系统般简便,却拥有528MHz主频处理器的“不凡”性能。
的头像 ZLG致远电子 发表于 03-23 08:29 3966次 阅读
一款跨界核心板,让物联网设计如MCU系统便捷

周立功现身说法:谈工程师如何克服职业痛点培养对市场的前瞻性

为什么很多工程师创业失败?其根本原因不是资金,而是因为不了解市场,对市场缺乏一定前瞻性的认识,做出来....
的头像 工程师人生 发表于 03-14 10:53 593次 阅读
周立功现身说法:谈工程师如何克服职业痛点培养对市场的前瞻性

ZLG携手NXP举行i.MX RT 跨界处理器全国巡回研讨会

2018年3月20号—4月3号,ZLG将携手NXP在全国6大城市(广州、深圳、上海、杭州、南京、北京....
的头像 ZLG致远电子 发表于 03-09 15:24 1478次 阅读
ZLG携手NXP举行i.MX RT 跨界处理器全国巡回研讨会

MCU+MPU双处理器架构在电力馈线终端中应用

目前市面上大多电力FTU产品均采用MCU+MPU双处理器架构,以利用MCU的实时性和MPU上运行的稳....
的头像 周立功单片机 发表于 03-05 08:41 1809次 阅读
MCU+MPU双处理器架构在电力馈线终端中应用

工业通讯现场,为何最担心浪涌产生的瞬态过压和过流!

各位工程师在工业通讯现场,最担心的是通讯网络因浪涌产生的瞬态过压和过流,导致总线通讯网络出现发送错误....
的头像 周立功单片机 发表于 02-28 08:42 1686次 阅读
工业通讯现场,为何最担心浪涌产生的瞬态过压和过流!

组建RS-485总线网络时,终端电阻实战案例

RS-485总线具有结构简单、成本低等优点,但各位工程师在组建RS-485总线网络时,为提升整个网络....
的头像 周立功单片机 发表于 02-08 09:51 2926次 阅读
组建RS-485总线网络时,终端电阻实战案例

如何使用RTC实时时钟进行应用场景开发

虽然该程序的逻辑与程序清单6.70 所示的应用程序基本一致,但由于使用的接口是特殊功能控制接口,与具....
的头像 周立功单片机 发表于 01-25 09:15 2385次 阅读
如何使用RTC实时时钟进行应用场景开发

13.56MHz读写卡模块通信接口及选型指南

论选择I2C 或UART 通信方式,只要基于实例句柄编程,则应用程序与具体的通信方式无关。
的头像 周立功单片机 发表于 01-25 09:09 2598次 阅读
13.56MHz读写卡模块通信接口及选型指南

键盘与数码管接口典型应用电路及寄存器

当矩阵扩大到一定数目时,逐行扫描的方法会显得费时,如果需要对2 个以上的按键“同时”操作时,则处理起....
的头像 周立功单片机 发表于 01-22 09:27 2931次 阅读
键盘与数码管接口典型应用电路及寄存器

如何理解软件设计原则和面向接口编程的开发思想

面向通用接口的编程,虽然面向接口的编程简单易懂,但无法做到最大程度上地重用应用程序,这是导致软件开发....
的头像 周立功单片机 发表于 01-22 09:11 3714次 阅读
如何理解软件设计原则和面向接口编程的开发思想

设计一个处理工资单数据包,继承与多态不可忽略!

虽然各种排序的实现不一样,但它们的共性都是“排序”,这就是抽象的基础。
的头像 周立功单片机 发表于 01-19 10:18 3557次 阅读
设计一个处理工资单数据包,继承与多态不可忽略!

温度传感器通用接口应用案例分析

对AMetal框架进行了详细介绍,通过阅读这本书,你可以学到高度复用的软件设计原则和面向接口编程的开....
的头像 周立功单片机 发表于 01-19 10:14 4446次 阅读
温度传感器通用接口应用案例分析

数码管与矩阵键盘联合应用设计

AMetal 提供了数码管和矩阵键盘联合使用的驱动,其本质上就是数码管驱动和矩阵键盘驱动的简单整合,....
的头像 周立功单片机 发表于 01-19 09:31 2699次 阅读
数码管与矩阵键盘联合应用设计

在LED通用接口的设计中,HC595主要作用

当前接口中的am_hc595_handle_t 类型为void *类型,最终,其需要是指向对象的指针....
的头像 周立功单片机 发表于 01-17 08:34 3182次 阅读
在LED通用接口的设计中,HC595主要作用

深入理解AMetal,掌握蜂鸣器和温度采集接口设计

在接口实现中,没有与硬件相关的实现代码,仅仅是简单的调用了抽象方法。抽象方法需要由具体的温度采集设备....
的头像 周立功单片机 发表于 01-17 08:29 3292次 阅读
深入理解AMetal,掌握蜂鸣器和温度采集接口设计

通用数码管与面向通用接口编程设计

数码管的各个段可以组合显示出多种图形,使用该函数可以自定义字符的解码函数
的头像 周立功单片机 发表于 01-10 09:13 3419次 阅读
通用数码管与面向通用接口编程设计

labview上位机,周立功USBCAN1卡,传输指令给电机驱动器

发表于 01-07 13:00 623次 阅读
labview上位机,周立功USBCAN1卡,传输指令给电机驱动器

二维数组作为函数参数传递在实际中的应用

由于表达式中的数组名data可以被解释为指针,即data的类型为指向int [2]的指针类型int ....
的头像 ZLG致远电子 发表于 12-20 07:19 2253次 阅读
二维数组作为函数参数传递在实际中的应用

Zigbee/蓝牙无线模块设计,那些难点知道多少?

为了便于快速开发,在AW824P2EF 内部已经将LPC824 的串口1与内置的zigbee 芯片的....
的头像 ZLG致远电子 发表于 12-20 07:04 3395次 阅读
Zigbee/蓝牙无线模块设计,那些难点知道多少?

EEPROM存储器外设及驱动代码应用设计

ZLG 为用户提供了大量标准的外设驱动与相关的协议组件,意在建立完整的生态系统。无论你选择什么MCU....
的头像 周立功单片机 发表于 12-20 06:28 4645次 阅读
EEPROM存储器外设及驱动代码应用设计

开发者在的很多管理者,需了解平台产品开发战略

在2017年9月5日深圳举行的“‘名家芯思维’之2017年物联网核心技术和应用国际研讨会”上,周立功....
的头像 ZLG致远电子 发表于 12-13 07:14 3612次 阅读
开发者在的很多管理者,需了解平台产品开发战略

周立功:深入浅出AMetal谈SPI总线和IIC 总线

在使用SPI 通用接口前,必须先完成SPI 的初始化,以获取标准的SPI 实例句柄。LPC82x支持....
的头像 周立功单片机 发表于 12-13 06:27 4285次 阅读
周立功:深入浅出AMetal谈SPI总线和IIC 总线

周立功:基于平台的产品开发战略

发表于 12-11 16:03 720次 阅读
周立功:基于平台的产品开发战略

周立功:改变观念及思维很重要!

物联网作为我国战略性新兴产业的重要组成部分,在加快经济发展、促进产业转型升级、服务社会民生方面正发挥....
的头像 Duke 发表于 12-11 11:47 3834次 阅读
周立功:改变观念及思维很重要!

周立功受88lifa利发国际娱乐邀请,参加2017第四届中国IoT大会

第四届中国物联网大会将于2017年12月6日在深圳召开,ZLG集团创始人周立功教授及ZLG致远电子工....
的头像 ZLG致远电子 发表于 12-06 06:39 3263次 阅读
周立功受88lifa利发国际娱乐邀请,参加2017第四届中国IoT大会

如何解决zigbee&BLE 模块最大的不足

。虽然大多数开发者都很勤奋,但其奋斗目标不是企业和个人收益最大化,而是以学习与MCU和zigbee&....
的头像 ZLG致远电子 发表于 12-06 06:30 3065次 阅读
如何解决zigbee&BLE 模块最大的不足

如何才能更好实现CAN模块之间数据传输

逻辑链接控制子层(LLC)、介质访问控制子层(MAC)、物理编码子层(PCS)。其中LLC包括接受过....
的头像 ZLG致远电子 发表于 11-29 06:25 4544次 阅读
如何才能更好实现CAN模块之间数据传输

深入了解AMetal框架,通用按键接口不可忽视

虽然使用单一的回调机制可以实现按键管理,但是,却使得按键检测模块的职责变得不单一,其不仅要处理与硬件....
的头像 ZLG致远电子 发表于 11-29 06:21 4693次 阅读
深入了解AMetal框架,通用按键接口不可忽视

LPC入门起步探讨,感觉LPCOpen例程包最好用

发表于 11-27 01:06 1313次 阅读
LPC入门起步探讨,感觉LPCOpen例程包最好用

事件驱动和键盘管理设计案例分析

在这种情况下,应尽可能地将相应功能设计为异步模式,即启动软件定时器,设定蜂鸣器鸣叫时间,打开蜂鸣器,....
的头像 ZLG致远电子 发表于 11-20 09:02 2144次 阅读
事件驱动和键盘管理设计案例分析

噪声和图像信号A/D 转换器深入解读

《面向AMetal框架与接口的编程(上)》一书对AMetal框架进行了详细介绍,通过阅读这本书,你可....
的头像 ZLG致远电子 发表于 11-20 08:54 4282次 阅读
噪声和图像信号A/D 转换器深入解读

无源蜂鸣器作为一种板载资源,该如何使用?

若用户不需要使用蜂鸣器,为了节省内存空间,可以将工程配置文件中的AM_CFG_BUZZER_ENAB....
的头像 ZLG致远电子 发表于 11-15 05:50 3989次 阅读
无源蜂鸣器作为一种板载资源,该如何使用?

面向对象编程——虚函数

周立功教授数年之心血之作《程序设计与数据结构》以及《面向AMetal框架与接口的编程(上)》,电子版....
的头像 ZLG致远电子 发表于 10-20 11:52 3206次 阅读
面向对象编程——虚函数

基于周立功CAN卡例程,显示某一特定ID报文数据的实时性问题

发表于 10-19 09:42 774次 阅读
基于周立功CAN卡例程,显示某一特定ID报文数据的实时性问题

State状态模式推导过程以及完整实现

由于在处理动作时,不需要任何数据,它是一个只有方法,没有属性的动作类,因此没有刻意使用结构体为其定义....
的头像 周立功单片机 发表于 10-17 06:42 4759次 阅读
State状态模式推导过程以及完整实现

【下载】新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

发表于 08-22 17:56 4982次 阅读
【下载】新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

发表于 08-21 14:58 860次 阅读
新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

庆祝周立功顺利入驻硬之城,优势料号大放送!

发表于 06-16 14:01 654次 阅读
庆祝周立功顺利入驻硬之城,优势料号大放送!

【下载】ARM嵌入式系统基础教程(周立功第2版)

发表于 06-12 17:59 6522次 阅读
【下载】ARM嵌入式系统基础教程(周立功第2版)

ARM嵌入式系统基础教程(第二版)周立功

发表于 05-24 15:00 1592次 阅读
ARM嵌入式系统基础教程(第二版)周立功

【完整资料】《程序设计与数据结构》周立功数十年心血力作

发表于 05-16 16:43 44717次 阅读
【完整资料】《程序设计与数据结构》周立功数十年心血力作

88lifa利发国际娱乐

百度360搜索搜狗搜索