发布时间:2012-06-30 阅读量:1874 来源: 我爱方案网 作者:
“串行”这个词大家或许都听得比较多,但是 “串行化”这个词有的朋友可能还比较陌生?那今天小编鱼丝我就来具体讲讲 “串行化”。
串行化的基本定义
串行化(Serialization)是计算机科学中的一个概念,它是指将对象存储到介质(如文件、内存缓冲区等)中或是以二进制方式通过网络传输。之后可以通过反串行化从这些连续的字节(byte)数据重新构建一个与原始对象状态相同的对象,因此在特定情况下也可以说是得到一个副本,但并不是所有情况都这样。
对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力,叫做对象的持续性(persistence)。对象通过写出描述自己状态的数值来记录自己,这个过程叫对象的串行化(Serialization)。
串行化的特性
串行化有以下但不局限于这些优点:
1.一种分布对象的方法,特别是在软件组件中,如COM、CORBA等
2.在随时间变化的数据(time-varying data)检测改变
3.串行化是一种更好地使用类持久化的方法
4.可用于远程方法调用,如SOAP
由于这些特性都是十分有用的,所以必须维持串行化的体系结构独立性。例如在一台运行在不同硬件构架上的计算机应该能够可靠地重新构建数据而不关心其对字节(byte)数据的编排方式(endianness)。
串行化的机制和原理
Seralization 又叫串行化,简单的讲,就是一种保存当前运行程序的状态,下次运行程序时可以将被保存的状态提取出来,这样就可以从上次保存的状态开始往后运行.在游戏设计中,这也就是所谓的存档/读档功能.
那么Seralization如何才能实现呢. 在结构化的程序设计中,函数(方法)和数据是相互独立的.
我们需要将当前内存块中的每个变量数据都保存到文件(后者是一个内存块,这点在下文提到)中,然后下次运行时在将这些数据都提取出来,付给每个变量. 比如说我的程序有两个全局变量Ea,Eb.有两个局部变量a,b. 其中a,b都是函数Fun 的局部变量.那么我需要保存这4个变量的值. 并且我要知道a,b是Fun的局部变量,Ea,Eb是全局变量. 并且我需要知道程序执行到哪一步了. 这是个复杂且难以完成的工作. 因此Seralization 都是在OOP 面向对象的原则下进行的. 甚至有的人直接称其为类的串行化.
基于OOP原则的程序, 类是数据和方法的集合. 我们只需要保存当前生存着的每个类中的数据, 类与类之间的关系, 当然如果有全局变量也需要保存. 下次还原时我们还原被保存的这些信息, 就还原了程序的状态.
这里就引入了几个问题.
1. 我们知道类继承机制中的虚函数机制可以动态的决定调用哪个函数. 比如:
Class A
{
Public:
Visual void fun() { return 1;};
}
Class B : public A
{
Public:
Virtual void fun(){ return 2;};
}
我定义一个指针 A* p = new B;
注意这里虽然p是一个A* 类的指针,但他实际上指向的是一个class B.
因此调用p->func 其实调用的是 B::func();
回到刚才的话题.类的成员函数如果被声明是虚函数的话,可以动态的决定调用哪个类的函数.但是类的创建必须要写成 A p = new A, 这里我们不能利用虚函数来实现动态的决定创建的是什么类.因为创建时程序还不知道p到底值向什么类.创建A类就必须写成new A,创建B类就必须写成new B. 这就是问题所在了.这个问题又被分为两个方面.首先,我们必须在保存类的信息时同时保存该类的类型
(是class A,还是 class B).这点可以利用RTTI的机制来实现.RTTI的原理很简单,我们在每个类中都添加一个字符串,这个字符串记录的这个类的类型名字.比如class A的字符串就是”A”,class B的字符串就是”B”.当我们保存的时候,我们把这个字符串也保存起来.这样当我们读取的时候就知道现在读取的数据是属于什么类的了.
然后我们需要解决的问题就是如果创建这个类了.前面说了.我们不能利用new 来创建,因为这里的创建是程序执行时动态决定的.我们事先不知道哪些类需要创建.这个问题我们利用object factory的思想来解决.我们为每种类都定义一个static factoryFunc();由于是static
的,所以该类的所以实例都共享这个方法,同时这个factoryFunc()是类相关的,不是实例相关的,因此在类还没被实例化之前就存在了(可以想像成全局的,从程序运行开始一直存在到程序结束). 我们将每个类的factoryFunc和该类的类型名(A,B)一起添加到一个map
容器中,一个类型名对应一个factoryFunc. factoryFunc封装了类的new 操作.这样我读取存档的时候.我只需要先读取类的类型名,然后到map里去查找这个类型名对应的factoryFunc,然后调用它来创建这个类就行了.伪代码如下
Read(stream, classname);
factoryFunc = Map->find(classname)
object* p = factoryFunc();
这样就实现了类的动态创建.
2.如何保存类之间的关系
这里我说类之间的关系就是指类的指针成员指向的其它类.由于我设计的引擎是以OOP为基础的.我定义了一个Object 类,并且认为其它一切的类都是这个类的派生类.注意最开始我们提到的保存机制保存了类的指针.但是如果我们新创建了一个类,那这个类的指针是系统自动分配的,和上次保存的地址是不一样的.因此不能简单的将当前类的指针成员的值保存下来,然后在读取出来重新付给它(因为现在这个值代表的内存块里的数据和上次不一样了).我们需要一个映射机制,能将旧的指针值和新的指针值对应起来.我这里也是利用的map来实现.
整个Seralization机制流程如下:
主要是2个类.Object , Stream
其中Stream里面有一个vector
无源晶振与有源晶振是电子系统中两种根本性的时钟元件,其核心区别在于是否内置振荡电路。晶振结构上的本质差异,直接决定了两者在应用场景、设计复杂度和成本上的不同。
RTC(实时时钟)电路广泛采用音叉型32.768kHz晶振作为时基源,但其频率稳定性对温度变化极为敏感。温度偏离常温基准(通常为25℃)时,频率会产生显著漂移,且偏离越远漂移越大。
有源晶振作为晶振的核心类别,凭借其内部集成振荡电路的独特设计,无需依赖外部电路即可独立工作,在电子设备中扮演着关键角色。本文将系统解析有源晶振的核心参数、电路设计及引脚接法,重点阐述其频率稳定度、老化率等关键指标,并结合实际电路图与引脚定义,帮助大家全面掌握有源晶振的应用要点,避免因接线错误导致器件失效。
晶振老化是影响其长期频率稳定性的核心因素,主要表现为输出频率随时间的缓慢漂移。无论是晶体谐振器还是晶体振荡器,在生产过程中均需经过针对性的防老化处理,但二者的工艺路径与耗时存在显著差异。
在现代汽车行业中,HUD平视显示系统正日益成为驾驶员的得力助手,为驾驶员提供实时导航、车辆信息和警示等功能,使驾驶更加安全和便捷。在HUD平视显示系统中,高精度的晶振是确保系统稳定运行的关键要素。YSX321SL是一款优质的3225无源晶振,拥有多项卓越特性,使其成为HUD平视显示系统的首选。