动态ICD配置的总线模拟器系统的制作方法

文档序号:12818697阅读:505来源:国知局
动态ICD配置的总线模拟器系统的制作方法与工艺

本发明涉及一种主要应用于航空电子设备联试场合的总线模拟器系统。



背景技术:

随着信息技术和计算机技术的发展,总线技术得到了广泛推广和应用。相比于传统的信息传递技术,总线具有信息数字化、接口标准化的特点,采用总线技术可以大大简化系统的设计,因此近年来得到了很快发展。由于航空电子总线模拟器系统包含的信号类型和参数类型非常复杂,而为了采集功能的全面性,方便采集多种总线类型和非总线类型的数据,总线模拟器系统包含现有的绝大多数信号类型,如1553b信号、422信号、429信号、afdx信号、can信号、网络信号、模拟量信号以及离散量信号;而总线模拟器系所包含的参数类型相比信号类型就要更复杂。这给总线模拟器系的界面显示模块和总线通信模块代码设计和实现造成了很大的困难,而且一旦接口控制文件(interfacecontroldocument,icd)icd发生变化,界面显示模块和总线通信模块代码就需要重新编写。

传统意义上,总线模拟器系统主要采用定制化开发模式,大致分为三个步骤:总体设计人员根据项目需求编制icd文档;软件人员按照界面显示层、业务逻辑层、总线驱动层的架构来编写总线模拟器系统,然后调试总线模拟器系统以达到使用要求。总线模拟器传统定制化开发过程中暴露出了人工工作量巨大、后期难以维护升级、不能有效积累工作成果、缺乏通用性等缺点,尤其是在界面显示层,由于icd少则几十条,多则上百条,每条icd内部又包含多个数据项,每个数据项会对应界面上的一个控件,粗略估计,往往会绘制上百甚至多达上千个控件,还要将每条icd内部的数据项组成一包完整的数据或者将一包完整的数据拆分成icd内部的数据项并映射到界面控件上,所有这些都要人工手动开发完成,这造成界面显示层的开发工作占整个系统开工作量的一半以上。由于不同主机所、不同型号的航电及功能的硬件、总线通信、icd差异比较大,经常发生更改和升级,这种僵硬的定制化开发模式造成总线模拟器系统后期维护困难,并耗费大量人力和物力。作为总线模拟器系统核心的界面控件自动生成技术,公开的有两种实现方式:

基于mfc框架,结合icd生成rc文件,然后在微软开发平台visualstudio的资源视图中加载生成的rc文件,软件开发人员在资源视图中以可视化的方式对界面控件进行微调,然后手动完成余下的开发工作;其次是基于wpf框架,用xaml语言描述icd对应的控件类型和控件布局,生成xaml文件,然后在微软开发平台visualstudio中加载生成的xaml文件,软件开发人员以可视化的方式对界面控件进行微调,然后手动完成余下的开发工作。

在上述两种实现方式中,rc文件和xaml文件都只提供对界面控件的描述,不能描述icd内部数据项的信息(包括数据类型、数据长度、编码方式等),仍然需要开发人员手动编码建立icd内部数据项与界面控件之间的关系,都不能实现框架复用,但使用xaml文件能够实现控件样式的复用。这两种实现方式都只在表面上部分解决了界面控件开发耗时的问题,并没有真正意义上实现界面控件的自动生成。



技术实现要素:

为了提高航空电子总线模拟器系统的开发效率和可靠性,降低测试工作的复杂度,本发明针对总线模拟器传统定制化开发过程中暴露出的人工工作量巨大、后期难以维护升级、不能有效积累工作成果、缺乏通用性等缺点,提供一种更具扩展性和复用性、适应性和通用性强、能够缩短研制周期,并能提高系统性能和可靠性的动态icd配置的总线模拟器系统。

本发明的上述目的可以通过以下措施来达到。一种动态icd配置的总线模拟器系统,包括:显示控制系统、总线通信系统、作为通信中间件的数据分发服务系统(datadistributionservice,dds)、界面配置文件生成工具,其特征在于:界面配置文件生成工具读入icd文档,开发人员使用界面配置文件生成工具设计出每一条icd中各个数据项对应的控件类型,然后生成界面配置文件;显示控制系统加载界面配置文件后动态地在界面上绘制出控件,显示控制系统和总线通信系统之间通过dds交互数据信息,当总线模拟器系统向总线发送数据时,由使用人员在显示控制系统中操作界面控件后,显示控制系统自主遍历与刚才所操作的icd绑定的一组控件并读取控件中的数值,然后按照大端序或者小端序的方式组包成dds数据帧,dds数据帧由通信中间件dds发往总线通信系统,总线通信系统根据总线映射关系,将dds数据帧转换成实际的总线数据并发送;当总线模拟器系统接收总线数据时,总线通信系统首先接收到实际的总线数据并根据总线映射关系转换成dds数据帧,dds数据帧由通信中间件dds发往显示控制系统,显示控制系统解析出数据并显示;在显示控制系统中,对界面控件的相对布局关系进行建模:三种基本的布局关系,“上下关系”、“左右关系”、“包含关系”,这三种布局关系可以相互嵌套组合成任意复杂的界面布局,界面配置文件以xml文件的格式来描述与icd中各个数据项对应的控件之间的相对布局关系,显示控制系统加载界面配置文件后解析出这种布局关系,采用递归的方式动态地绘制出控件并按照相对布局关系的约束自动地调整控件位置;显示控制系统和总线通信系统分别是一个单独的软件,显示控制系统的输入输出总是dds数据帧,通信中间件dds实现显示控制系统与总线通信系统之间的数据通信,总线通信系统根据总线映射关系实现dds数据帧与总线数据帧的互相转换,这使得显示控制系统与实际总线解耦。本发明使用的编程语言是c++,其他面向对象的语言也能用于本发明的实现。

本发明相比于现有技术具有如下有益效果。

更具扩展性和复用性。本发明根据icd文件生成界面配置文件,总线模拟器系统加载界面配置文件动态生成界面控件,自动实现icd数据的组包和解包,通过界面配置文件生成工具可以快捷地将xml格式的icd文件转换成界面配置文件,支持常用的控件类型,包括按钮button、编辑框edit、检查框checkbox、下拉框combobox、列表list、按钮组radiogroup等。采用面向对象的方式构造系统,使得系统便于扩展与维护,可以通过继承的方式增加能够自动生成的新控件类型与新总线驱动器。这种采用面向对象的方法对界面控件自动生成过程进行建模,同时应用了软件设计模式,相比于现有的两种界面控件自动生成技术,把icd内部数据项的信息和界面控件的信息结合起来,自动建立icd内部数据项与界面控件之间的数据通道,实现框架级的复用,并且通过更换界面配置文件的方式实现了显示控制系统在不同项目之间的复用。这相比传统面向过程的系统更具扩展性。

适应性和通用性强。本发明增加新的控件类型和总线类型十分方便。通过将界面控件生成、icd数据组包、icd数据解析等过程自动化,大大减少了总线模拟器系统开发过程中重复性的脑力劳动,保证了软件质量,缩短了开发周期,增加了总线模拟器系统在各个型号项目中的复用性。可以根据界面配置文件工具在系统运行时自动绘制控件界面,不再需要手动编写界面绘制代码,icd文件更新后只需用新的界面配置文件替换旧的界面配置文件而无需更改代码和重新编译程序就能实现总线模拟器的升级。在使用需求或icd总线协议发生变化时,只需修改相应的界面配置文件,就可自动生成新的界面控件布局,增强了软件的适应性和通用性。

缩短了研制周期。本发明以基于icd文件动态配置界面控件的方式实现了控件的自动生成,大大减少了人工开发工作量。由系统在运行时自动关联控件和数据项,而不是在编译时由人工用代码关联,大大节省航电模拟器系统开发时间,保证系统运行的可靠性与一致性。通过将界面控件生成、icd数据解包与组包等过程自动化,大大减少了总线模拟器系统开发过程中重复性的脑力劳动,保证了软件质量,缩短了开发周期,增加了总线模拟器系统在各个型号项目中的复用性。

提高了系统性能和可靠性。本发明采用icd数据解包接口将计算机内存中的数据按照icd内部数据项的先后顺序,根据所占的比特位数映射到对应的控件上并显示出来;icd数据组包与icd数据解包互为逆过程,使用面向对象的方法对界面控件的相对布局关系及控件本身进行建模,通过读取界面配置文件,按照界面配置文件的树形层次结构生成相应的控件并进行自动布局。通过使用dds实现总线模拟器与底层驱动的解耦,支持总线模拟器系统的单机和分布式部署,提高了系统性能和可靠性。

本发明可用于代替航空电子各子系统产生航电总线信号,并代替这些子系统处理和显示航电总线信号。

附图说明

下面结合附图对本发明专利进一步说明。

图1是本发明动态icd配置的总线模拟器系统的架构示意图。

图2是图1的工作原理示意图。

图3是图1的接口控制文件icd结构示意图。

图4是图1的界面配置文件结构示意图。

图5是图1的控件数据映射图。

图6是图1的控件布局建模示意图。

图7是图1的实体控件数据组包/解包过程。

图8是图1的接口控制文件icd数据组包/解包流程图。

图9是图1的控件布局类图。

图10是图1的驱动类图。

具体实施方式

参阅图1。在以下描述的实施例中,一种动态icd配置的总线模拟器系统,包括:显示控制系统、总线通信系统、作为通信中间件的数据分发服务系统(datadistributionservice,dds)、界面配置文件生成工具,其中:显示控制系统包括:icd数据解包器、icd数据组包器、界面控件自动生成器、dds通信接口组件,界面控件自动生成器又包括:button控件生成器、checkbox控件生成器、combobox控件生成器、list控件生成器、radiogroup控件生成器,总线通信系统包括:dds通信接口组件、总线数据转发器、总线驱动器,界面配置文件生成工具包括:icd内容解析器、界面配置文件生成器。显示控制系统与总线通信系统之间通过数据分发服务系统dds通信中间件交互dds数据帧,总线通信系统根据总线映射关系将dds数据帧转换成实际的总线数据并发送;开发人员使用界面配置文件生成工具读入icd后设计出每一条icd中各个数据项对应的控件类型,然后生成界面配置文件,显示控制系统加载界面配置文件并自动绘制控件界面。在显示控制系统中,界面控件自动生成器遍历界面配置文件,根据界面配置文件中每个数据项的控件类型动态绘制出相应控件,建立数据项与控件的映射关系,以递归的方式建立控件树,以控件树为基础实现控件自动布局,注册自定义的windows消息响应用户界面发送数据的操作。显示控制系统响应用户界面发送数据的操作启动icd数据组包器。icd数据组包器开辟一段空闲内存块,遍历控件树,由数据项与控件的映射关系取出控件的当前值并存入数据项,以内存块的基地址为位偏移起始位置并加上数据项的位偏移量作为数据项中数据的存放地址,以数据项的位域宽度作为数据项中的数据在内存块中的存放长度。显示控制系统刚启动时,以icd名称作为主题名称向dds通信接口组件分两类进行注册,需要发送的icd以“发布”的方式注册,需要接收的icd以“订阅”的方式注册。icd数据组包器完成工作后启动dds通信接口组件,以icd名称、组包后的内存块首地址及内存块长度作为参数调用dds通信接口组件的数据发布函数。当显示控制系统“订阅”的数据包到来时,icd数据解包器将会根据dds数据帧的主题名称定位到接口控制文件icd,再由接口控制文件icd标识符再定位到控件树,遍历控件树,根据数据项的位域宽度、位偏移量描述从接收内存块中取出数据并存入与控件绑定的数据项中,然后刷新控件。

界面配置文件生成工具根据icd文件生成界面配置文件,界面配置文件中包含了对icd数据、总线、界面控件等信息的描述。在界面配置文件生成工具中,icd内容解析器加载并分析接口控制文件icd文档,界面配置文件生成器根据icd内容解析器的解析结果为icd内部数据项中的整型数据选择edit控件,为具有3个及以上枚举值的枚举型数据选择combobox控件,为具有2个及以下枚举值的枚举型数据选择radiogroup控件、为具有变长数据结构的数据类型选择list控件。这些都是默认设置,开发人员可以在操作界面上做微调,比如:改变控件的类型、改变枚举值等。界面配置文件生成器界面配置文件生成工具不仅可以生成新的界面配置文件,也能加载已有的界面配置文件以便于界面配置文件的管理与维护。

显示控制系统通过加载界面配置文件动态生成界面控件并自动布局,自动实现icd数据组包与解包,支持大端序和小端序的icd数据格式。在总线通信系统中,封装总线驱动,抽象出总线的一般接口,包含一个总线数据转发器,总线数据转发器根据数据转发规则将总线数据由一个总线接口发往另一个总线接口,借助编程语言(c++)的多态性质,具体的总线类型在总线数据转发子系统运行时确定,总线数据转发器的一端确定使用dds通信接口组件,另一端根据具体项目确定,可以是afdx、1394、can、485、422等总线中的任意一种。

总线通信系统封装了底层板卡驱动,发送icd数据时,从dds接收数据并转发到总线上,接收icd数据时,从总线接收数据并转发到dds;dds通过“发布-订阅”icd标识符的方式来实现数据的交互,发送icd数据时,显示控制系统是发布方,总线通信系统是订阅方,接收icd数据时,总线通信系统是发布方,显示控制系统是订阅方。显示控制系统和总线通信系统挂载到dds上,dds通过“发布-订阅”的方式作为显示控制系统和总线通信系统之间的数据沟通媒介;由总线通信系统“订阅”的数据路由到实际的总线驱动并发送出去,由显示控制系统“订阅”的数据由icd数据解包器处理。除了使用dds以外,还可以使用其他的进程通信方式实现显示控制系统与总线通信系统之间的数据交互,比如:共享内存、管道等;只要以指定格式封装总线就能支持其他的总线驱动器。

显示控制系统加载界面配置文件后动态地在界面上绘制出控件,显示控制系统和总线通信系统之间通过dds交互数据信息,当总线模拟器系统向总线发送数据时,由使用人员在显示控制系统中操作界面控件后,显示控制系统自主遍历与刚才所操作的icd绑定的一组控件并读取控件中的数值,然后按照大端序或者小端序的方式组包成dds数据帧,dds数据帧由通信中间件dds发往总线通信系统,总线通信系统根据总线映射关系,将dds数据帧转换成实际的总线数据并发送;当总线模拟器系统接收总线数据时,总线通信系统首先接收到实际的总线数据并根据总线映射关系转换成dds数据帧,dds数据帧由通信中间件dds发往显示控制系统,显示控制系统解析出数据并显示;在显示控制系统中,对界面控件的相对布局关系进行建模:三种基本的布局关系,“上下关系”、“左右关系”、“包含关系”,这三种布局关系可以相互嵌套组合成任意复杂的界面布局,界面配置文件以xml文件的格式来描述与icd中各个数据项对应的控件之间的相对布局关系,显示控制系统加载界面配置文件后解析出这种布局关系,采用递归的方式动态地绘制出控件并按照相对布局关系的约束自动地调整控件位置;显示控制系统和总线通信系统分别是一个单独的软件,通信中间件dds是一个商用软件,显示控制系统的输入输出总是dds数据帧,通信中间件dds实现显示控制系统与总线通信系统之间的数据通信,总线通信系统根据总线映射关系实现dds数据帧与总线数据帧的互相转换,这使得显示控制系统与实际总线解耦。

参阅图2。界面配置文件生成工具将读入的接口控制文件icd送入icd内容解析器,icd内容解析器将获取的icd中数据项的数据类型、位域宽度等信息输入界面配置文件生成器,界面配置文件生成器根据上述信息得到默认配置下的控件类型界面配置文件,并送入显示控制系统,通过界面配置文件生成器生成界面配置文件,并加载界面配置文件,自动布局动态地生成的控件。加载界面配置文件可以通过操作人员也可在操作界面上更改上述配置。在显示控制系统中,当用户在显示控制系统上选择发送icd数据时,显示控制系统的界面控件自动生成器找到与icd对应的控件树,遍历控件树icd数据组包,icd数据组包数据通过dds通信中间件接口发往dds通信中间件,dds通信中间件组包数据送入总线通信系统。在总线通信系统中。dds通信中间件将上述组包数据送入总线通信系统中的dds驱动器,dds驱动器将收到的dds数据帧送入总线数据转发器,路由到实际的总线驱动器并发送到实际的总线上。实际的总线包括:429总线驱动器、afd总线驱动器、422总线驱动器、485总线驱动器、、以太网总线驱动器和fc总线驱动器。当实际的总线数据到来时,实际的总线驱动器将会收到数据,实际的总线数据帧经总线数据转发器路由到dds总线驱动器,dds总线驱动器将数据发往dds通信中间件,显示控制系统的dds通信中间件接口收到dds数据帧,显示控制系统将dds数据帧送往界面控件自动生成器,界面控件自动生成器遍历控件树完成icd数据解包并刷新控件。

参阅图3。icd文件以xml方式实现原始输入文件。icd文件由总线、消息、主题、信号组、信号,四部分组成。信号是最基本的功能单元,包括:总线编号、总线名称、总线帧头、总线帧尾和总线描述;消息包括:消息编号、引用主题编号、引用主题编号、、消息定义名称和消息定义别名;主题包括主题编号、引用信号和主题名称,引用信号包含信号和信号组;信号组包括:信号组编号、信号组名称、位域宽度和引用信号;信号包括:信号编号。信号名称、信号描述、信号类型和位域宽度。通过信号、信号组、主题、总线的复用避免了重复数据项的多次定义。引用方式的复用使得只需修改被引用项,所有引用它的地方自然而然地跟着变化不需要再手动更改,这使得icd的更新变得更容易。

参阅图4。参阅图4。界面配置文件生成工具以xml方式生成界面配置文件,输出界面配置文件。界面配置文件生成工具由页面、icd面板两部分组成。页面包括:页面名称、引用的icd面板和页面别名。icd面板包括:面板名称、面板别名、数据项、消息id和消息长度,其中,数据项包含:数据项名称、数据项别名、枚举项、、位偏移量、域宽度、默认值和控件类型,其中,枚举项包含数值和枚举描述。页面是存放icd面板的容器,可以引用多个icd面板。icd面板中包含多个数据项,每一个数据项都包含了最重要的三个属性:位偏移量、位域宽度、控件类型。位偏移量以0算起,一个数据项的位偏移量是位于它之前的所有数据项的位域宽度之和。控件类型包括:下拉框combobox、按钮组radiogroup、文本框textedit、列表list等。

参阅图5。在控件数据映射中,控件1、控件2…控件n分别对应icd数据项1、数据项2…数据项n。一条icd包含多个数据项,每一个数据项对应一个控件。当操作人员在显示控制系统上选择发送一条icd时,显示控制系统的icd数据组包器根据控件与数据项的绑定关系获取到对应数据项的值,然后将所有数据项的值组包获取到一条icd对应的二进制源码;当显示控制系统解析一条icd时,显示控制系统的icd数据解包器根据数据项在icd中的位偏移量,操纵一个字符型指针在二进制源码上,做偏移获取对应数据项的源码值,然后据此更新与数据项绑定的控件值。

参阅图6。在控件布局建模中,控件包含:左右嵌套控件、上下嵌套控件、包含嵌套控件、实体控件。左右嵌套控件由左控件、右控件构成;上下嵌套控件由上控件、下控件构成;包含嵌套控件由外控件、内控件构成;左控件、右控件、上控件、下控件、外控件、内控件由控件构成,而控件可以是左右嵌套控件、上下嵌套控件、包含嵌套控件、实体控件中的任意一种。这种循环嵌套的结构支撑起整个控件布局。

参阅图7。显示控制系统给定存放在数据内存址pbuffer、位偏移量nbitoffset、数据所占项的比特数nbit,其中,数据项的内存地址等于存放整条icd数据的内存首地址加上位偏移量。采用,整条icd数据的内存首地址、位偏移量nbitoffset、数据项的位域宽度为实体控件数据组包时,将与实体控件绑定的数据项内容取出并存入数据项的内存地址;实体控件数据解包时,在数据项内存地址中取出数据值,数据的取出位宽由数据项的位域宽度决定,按大端存储数据方式是则按大端方式在数据内存址pbuffer中存取数据,否则按小端方式在数据内存址pbuffer中存取数据,并更新数据内存址pbuffer与位偏移量nbitoffset,将取出的数据值存入与实体控件绑定的数据项,然后刷新控件显示新值,完成数据组包或者数据解包后,更新内存地址和位偏移量。

参阅图8。将控件树中根节点控件rootnode赋予当前处理控件pcurnode,然后定义两个控件临时变量:pnode1、pnode2。如果pcurnode是左右嵌套控件,将pcurnode嵌套的左控件赋予pnode1,将pcurnode嵌套的的右控件赋予pnode2。如果pcurnode不是左右嵌套控件,则判断pcurnode是否为上下嵌套控件。如果pcurnode是上下嵌套控件,将pcurnode嵌套的上控件赋予pnode1,将pcurnode嵌套的的下控件赋予pnode2。如果pcurnode不是上下嵌套控件,则判断pcurnode是否为包含嵌套控件。如果pcurnode是包含嵌套控件,将pcurnode嵌套的外控件赋予pnode1,将pcurnode嵌套的的内控件赋予pnode2。如果pcurnode不是左右嵌套控件、上下嵌套控件、包含嵌套控件中的任何一种则进行出错处理,然后当次处理结束。当对pcurnode的控件类型判断完成并赋予pnode1、pnode2值以后,接着对pnode1、pnode2进行控件类型判断。如果pnode1不是实体控件,则将pnode1赋予pcurnode继续做下一次递归处理。如果pnode1是实体控件,则对pnode1控件进行数据组包/解包。在pnode1是实体控件的条件下,如果pnode2不是实体控件,则将pnode2赋予pcurnode继续做下一次递归处理。在pnode1是实体控件的条件下,如果pnode2也是实体控件,则对pnode2控件进行数据组包/解包,然后当次处理结束。整个处理流程的递归调用始于对当前处理控件pcurnode控件的处理,初始状态下,pcurnode为控件树中的根节点控件,在递归处理过程中,pcurnode为控件树中的嵌套控件。

参阅图9。在显示控制系统的控件树的软件实现中,对控件树的节点进行面向对象建模。控件树中有两类控件节点:实体控件节点、嵌套控件节点(包含:左右嵌套控件节点、上下嵌套控件、包含嵌套节点)。实体控件节点因为不能嵌套其他控件,所以就只能是控件树的叶节点。嵌套控件节点因为需要嵌套其他的控件,所以它必然作为控件树的中间节点,而且嵌套控件节点的子节点可以是实体控件节点也可以是另外的嵌套控件节点。因为每一个嵌套控件节点都有两个子节点,所以这样形成的控件树就是一颗二叉树。cnode是控件树中所有控件类型节点的抽象基类。包含嵌套控件类frmctrl、左右嵌套控件类hcatcrlctrl、上下嵌套控件类vcatcrlctrl、实体控件类rawctrl都继承于cnode。contrl是一个控件包装类,在contrl类中有一个指向cnode型对象的指针pnode。一个contrl类的实例化对象可以看做是一个控件,这个控件的类型由pnode实际指向的对象类型决定(可以是frmctrl、hcatcrlctrl、vcatcrlctrl、rawctrl中任意一种,因为它们都继承于cnode,所以它们都是cnode型对象,因此指向它们的指针可以赋值给pnode)。在frmctrl中,poutctrl和pinctrl都是指向contrl型对象的指针,poutctrl指向外控件,pinctrl指向内控件;在hcatcrlctrl中,pleftctrl和prightctrl都是指向contrl型对象的指针,pleftctrl指向左控件,prightctrl指向右控件;在vcatcrlctrl中,pupctrl和pdownctrl都是指向contrl型对象的指针,pupctrl指向上控件,pdownctrl指向下控件。按钮组类cradiogroupbox、下拉框类ccombobox、文本框类ctextedit、列表类clist都继承于通用控件基类ctrlcommclass。实体控件类rawctrl中有一个指向通用控件基类ctrlcommclass的一个指针pctrlcomm。实体控件的具体类型由pctrlcomm实际指向的对象类型决定(可以是cradiogroupbox、ccombobox、ctextedit、clist中任意一种,因为它们都继承于ctrlcommclass,所以它们都是ctrlcommclass型对象,因此指向它们的指针可以赋值给pctrlcomm)。display()是控件布局函数,在控件自动布局的过程中,在contrl类中调用pnode->display();在frmctrl类的布局函数display()中先后调用poutctrl->display()和pinctrl->display();在hcatcrlctrl类的布局函数display()中先后调用pleftctrl->display()和prightctrl->display();在vcatcrlctrl类的布局函数display()中先后调用pupctrl->display()和pdownctrl->display();在rawctrl类的布局函数display()中,调用pctrlcomm->display()。frmctrl类、hcatcrlctrl类、vcatcrlctrl类、rawctrl类继承于cnode类并实现display()函数,根据c++语言的多态性,contrl类display()中pnode->display()执行的是pnode实际指向类型的display()版本。cradiogroupbox类、ccombobox类、ctextedit类、clist类继承于ctrlcommclass类并实现display()函数,根据c++语言的多态性,rawctrl类display()中pctrlcomm->display()执行的是pctrlcomm实际指向类型的display()版本。因此,嵌套控件的布局函数display()会调用被嵌套控件的布局函数display(),实体控件的布局函数display()会将控件实际绘出,只调用控件树根节点所属类型contrl类的布局函数display()就会触发在控件树的每一层子节点递归调用布局函数display()直到绘制出控件树上的所有控件,这样就实现了控件的自动布局。

参阅图10。在总线通信系统的驱动类图中,driverlistenerhandler是总线监听基类,其中的虚函数onrecvdata()用于处理接收到的总线数据,总线驱动映射器类drivermap继承于driverlistenerhandler,实现虚函数onrecvdata()。drivercreator是总线驱动生成器类,函数createdriver()用于生成总线驱动。drivermap中有一个指向总线驱动生成器类drivercreator的指针pdricrt。busdriver是总线驱动基类,其中,setlistenerhandler()函数用于注册总线监听类对象,虚函数initdriver()用于总线驱动的初始化,虚函数send()用于发送总线数据。dds驱动器类ddsdriver、afdx总线驱动器类afdxdriver、can总线驱动器类candriver继承于busdriver并实现虚函数initdriver()和send()。每一个总线映射关系中包含一对总线驱动,一个是dds驱动,一个是实际的总线驱动。drivermap类建立总线映射关系表时,drivermap类调用pdricrt->createdriver()获得总线驱动器。在drivercreator类的createdriver()实现中,首先定义一个busdriver型的指针pbusdriver并赋初值为0,然后根据总线类型type生成对应的总线驱动。如果type等于driver_dds,则new一个ddsdriver对象并将其指针赋予pbusdriver;如果type等于driver_afdx,则new一个afdxdriver对象并将其指针赋予pbusdriver;如果type等于driver_can,则new一个candriver对象并将其指针赋予pbusdriver,然后返回pbusdriver。drivermap类每获得一个总线驱动器时,drivermap类调用busdriver类的setlistenerhandler()函数注册自己,如此在驱动器接收到实际的总线数据时调用driverlistenerhandler类的onrecvdata()函数,根据c++语言的多态性,实际调用的将是drivermap类的onrecvdata()函数。在drivermap类的onrecvdata()函数实现中,首先定义一个busdriver型的指针pdestdriver并赋初值为0,然后根据源驱动器查找总线映射关系表,找到对应的目的驱动器并赋值给pdestdriver,调用pdestdriver->send()发送数据。因为send()是虚函数,pdestdriver->send()执行的是pdestdriver实际指向驱动器类型的send()函数版本。通过使用总线驱动基类busdriver实现了总线驱动类与总线驱动映射器类drivermap之间的解耦,总线驱动映射器类只是用总线驱动基类busdriver提供的虚函数实现相应的业务而不关心是哪一种具体的总线驱动实现了上述的虚函数,这使得增加新的总线驱动器类十分方便,只需新增一个继承于busdriver的类,在createdriver()函数中增加新总线驱动器的创建语句,总线驱动映射器类drivermap不做任何修改。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1