为C 程式添加文档保存加载功能

2008-02-23 05:27:27来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

一、引子

  为什么要浪费时间去设计一个算法来实现数据的文档存储还要费劲地调试代码呢?Boost库能够为您做这些事情。借助于串行化模板,您能够容易地把数据存储到您自己定制格式的文档中。本文将教给您如何轻松地存储数据并回读数据。

  二、概述

  当您研发一个软件包时,您总是想集中精力于软件的功能。而最让您担心的是,花费大量的时间写代码,而该代码有可能会应用在另外大量的其他程式中。那正是重用的含义所在,您会希望另外某人已为您编写出这样现成的代码。

  这类问题的一个很好的例子是给予您的程式存档的能力。例如,您可能在写最伟大的天文学程式-在该程式中,您的用户能够轻易地输入时间和坐标,您的程式负责绘制当前天空的地图。但是,假定您赋予您的用户能够高亮某些星星,这样以来他们能够容易地突出在地图上。最后,您让用户能够保存他们的配置以备后用。

  您的程式集中于天文学编程。您并不是在写一个通用库来保存文档,所以您不必把大量的时间花在存储功能上,因为您要专注于程式的天文学特性。假如您是用C 编程,您能够从Boost重用库得到帮助。为了保存文档,Boost库包括一个串行化类,正是您需要的。

  假如您成功地创建了您的程式工程,很可能有一个类来包含用户信息或文档。例如,您可能有一个类,该类列举用户们最喜欢的星星的名字和位置。(请原谅这里的简化)。这就是您希望用户能够保存到磁盘上的数据。毕竟,几乎任何的程式都有文档保存功能。微软的Word保存文本和格式化数据,而Excel保存工作单数据。一个优秀的地图程式能够用户保存喜欢的位置,GPS路线,旅程,等等。

  借助于Boost串行化库的帮助,实现保存很容易-所要做是仅仅是配置好您的类,而由库来负责其他一切-使您专注于真正的工作。

  其思想是很简单的:您创建了一个包含用户数据的对象。当准备保存信息时,用户选择File|Save As,然后从文档对话框中选择一个文档名即可。借助于Boost,您的程式就把数据保存到选定的文档中。以后,当用户重新启动该程式时,选择File|Open,选定已保存的文档,您的程式再一次使用Boost-但是这一次重新装入数据,因此,重新产生了该对象。瞧,用户数据被回复了!或,从用户的角度来看,文档已被打开。

  下面的例子只是简单地演示保存和加载一些图像类。第一个类,Vertex,描述了一个二维的点。第二个类,Polygon,包含一个Vertex实例的容器。第三个类,Drawing,包含一个Polygon的容器。

  想把任何这些都保存到一个文档中去无疑是个恶梦-这不是花费时间的地方-您要实现最好的图像程式设计,因为这是您的专长。好了,让Boost库为您做其他一切吧。

  三、串行化一个类

  首先,考虑一下Vertex类。该类是最容易串行化的一个,因为他不包含其他对象。该类包含两个值,x和y,且都是double型。我还给该类定义了几个存取x和y的函数,更有一个dump函数,他负责把x和y的值输送到控制台。最后,我包含了两个构造器,一个是缺省的,另一个用作输入参数。(为了简化起见,该例程并没有做任何实际的绘图。抱歉!)

  下面最吸引人的部分是必需的代码行以串行化该类。下面就是该类(注意粗体部分):

class Vertex {
 private:
  friend class boost::serialization::access;
  template<class Archive>
  void serialize(Archive & ar, const unsigned int version)
  {
   ar & x;
   ar & y;
  }
  double x;
  double y;
 public:
  Vertex() {} // 串行化需要一个缺省的构造器
  Vertex(double newX, double newY) : x(newX), y(newY) {}
  double getX() const { return x; }
  double getY() const { return y; }
  void dump() {
   cout << x << " " << y << endl;
  }
};

  注意在程式的最后,我没有实际地使用缺省的构造器Vertex(),但是串行化库的确调用了他,因此我需要把他包含进去。

  串行化部分首先串行化库存取私有成员,特别是接下来的串行化函数。串行化库的创建者Robert Ramey指出,您无需任何的函数,包括在派生类中的那些,调用您的串行化方法;只需由串行化库来调用即可。因此,为了保护您的类,需要把串行化功能声明为私有的,然后允许有限制地存取该串行化库,这通过把类boost::serialization::access声明为您的类的友元来实现,见代码。

  接下去是串行化函数,他是个模板函数。假如您对模板还不太熟悉的话,不要紧:您无需理解模板部分而照旧能够使之工作。然而,必须确保您理解了串行化功能的核心:

ar & x;
ar & y;

  首先,让我声明一下:这两行代码并不是声明参照引用变量,虽然形式上看上去相似。代之的是,他们调用一个&操作符,并且把您的类成员写入到文档中或把他们读进来。是的,您已正确地认出了;该功能实现了一石二鸟(或更准确地说,用一套代码完成了两件任务)的功效。当您在把一个Vertex对象保存到一个文档中去时,串行化库调用这个串行化功能;第一行把x的值写入到文档中,第二行把y的值写入到文档中。后来,当您把一个Vertex对象从文档中读回时,第一行实现从文档中读回x值,第二行实现从文档中读回y值。

  这是某种特别的操作符重载!事实上,&字符是个在串行化库内部定义的一个操作符。幸好您无需理解他是如何工作的。

  好,就是那么简单。下面是一些示例代码,您能够试着把一个Vertex 对象保存到一个文档中:

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: Bjarne:怎样从输入中读取一个字符串?

下一篇: C 将DBGrid中数据导出到Word和Excel

Vertex v1(1.5, 2.5);
std::ofstream ofs("myfile.vtx");
boost::archive::text_oarchive oa(ofs);
oa << v1;
ofs.close();