日期:2012-03-03  浏览次数:20891 次

    
    C++是标准化的计算机语言,不属于任何人,而属于一个标准委员会。STL是支持数据结构和算法的C++扩展。ATL是微软拥有和维护的模板库,使得COM编程更容易。综合这些技术形成了创建COM组件的一种有效方法,这些COM组件用于ASP页面。
    下面用所有这些技术创建一个COM对象,你将看到VC++ 6.0的向导如何提供大量代码,因此,可以把注意力集中在解决问题上,而不是担心具体的编程细节。
    17.3.1 问题
    表现数据的最普通方法是表,列代表字段的类型,每一行是一条记录,拥有字段的值。在文本文件中,表通常由用逗号分开的值(comma-separated values,CSV)组成。
    我们将要创建的COM组件以CSV数据作为输入,高效地存储它,并提供访问函数去检索它。这些数据在COM组件中以STL数据结构表示。在以后部分中,我们会看到怎样用STL算法去处理这些数据。另外,在下一章,将介绍怎样在数据库中存储存这些数据。
    为了便于说明,假设数据在一个稀疏表中。第一行的字段是列标题,接下来的是一条条数据记录,记录的每个字段对齐于列标题。逗号隔离字段,换行符(/n)隔离行,空的字段用两个逗号表示,即“,,”。
    表17-1是一个展开的表的例子。导出时,逗号会隔离每一个字段。

17.3.2 设计
    这个组件的设计目的是使数据的存储空间和访问时间最小。由于数据有可能是稀疏的,即许多字段是空的,这就有可能使数据的存储空间最小化。可以通过数值(基于零的索引)访问数据的行,可以通过字段名访问数据的列。例如,要得到表17-1中Keith Moon的Instrument,可以调用GetField (1,"Instrument")。
    完成以上工作的工具是STL的vector和map数据结构,这些数据结构是容器,就是说,它们是包含其他对象的一个集合的对象。为了访问集合中的对象,使用STL遍历器。
17.3.3 实现
    现在你对这个组件的功能已经有了概念,我们将按下面的步骤实现它:
    ? 创建包含组件的DLL。
    ? 创建组件。
    ? 增加属性。
    ? 增加方法。
    1. 创建DLL和一个组件
    选择ATLCOMAppWizard,创建一个新的VC++项目,然后命名为ASPCOMponents。使用默认的服务器类型(DLL),不选中复选框,如图17-1所示。

    当完成后,这个向导会自动产生一个组件的外壳。这时没有组件存在,只有DLL根据COM规范所要求的函数存在,可以在ASPCOMponents.cpp文件中看到这些函数,但不用关心文件的细节,也不用改变它。当向DLL中添加组件时,向导会修改该文件。
    现在将组件放入DLL。在工作区窗口选择ClassView选项卡,右击ASPComponents Classes,选择New ATL Object。然后再选Simple Object,并且在Short Name框中键入Tablestorage,如图17 - 2所示。

    除非你打算更深入地研究ATL,否则在Attributes选项卡保持默认状态,不必改变任何选项。对所有这些选项的意义的详细描述已超出本书的范围。Attributes选项卡如图17-3所示。
    点击OK后,就有了一个用来工作的对象。

    到目前为止,VC++向导已经完成了所有的工作,如果查看TableStorage.h,你会看到向导产生的ATL代码。在大多数情况下,不必改变这些代码。实际上,可以只依靠这些代码,不用了解ATL,继续进行编程。然而,需要对默认的设置做一点改变,使得生成的代码能够编译。
    为了减小组件的大小,当AppWizard创建一个组件时,自动关闭C++的异常处理。因为如果启用这一功能的话,则需要C运行期库。STL使用异常处理,所以需要启用它。在ProjectSettings对话框的C/C++选项卡中,下拉Category框选择C++ Language,确保Settings for框设置为All Configurations,选择Enable exception handing复选框,如图1 7 - 4所示。

     如果用Release模式编译可能会得到一个链接错误。当编译一个发行版本的ATL项目时,如果异常处理没有关闭,会出现这样的问题。使用异常处理时,需要C运行期启动代码;但是在默认方式下,Release模式的ATL项目定义了_ ATL _MIN_CRT符号,它拒绝启动代码。为了解决这个问题,在C/C++预处理器定义中删除_ ATL_MIN_CRT。详细资料请看微软基础知识库中的文章Q165259。
    我们增加的第一段代码用于建立STL数据结构,把下列代码加到TableStorage.h的开头:

    这里,声明了两个映射和一个矢量。这个矢量实际是两个映射之一的矢量。使用C++的typedef命令定义映射和矢量主要是为了使得代码更易读,对数据类型描述得更好。
    COLUMN_INDEX_MAP将一个字符串(列的名称)映射到一个索引中。INDEX_FIELD_