当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++基础入门教程

全面掌握C++字符串封装类

  因为C语言风格的字符串容易出错且不易管理,黑客们甚至利用可能存在的缓冲区溢出bug把C语言风格的字符串作为攻击目标,所以出现了很多字符串封装 类。不幸的是,在某些场合下我们不知道该使用哪个字符串类,也不知道怎样把一个C风格的字符串转换成一个字符串封装类。
  这篇文章将介绍所有在Win32 API, MFC, STL, WTL 和 Visual C++ 运行库中出现的字符串类型。我将描述每一个类的用法,告诉大家怎样创建每一个类的对象以及怎样把一个类转换成其他类。受控字符串和Visual C++ 7中的类两部分是Nish完成的。
  为了更好的从这篇文章中受益,你必须要明白不同的字符类型和编码,这些内容我在第一部分中介绍过。
Rule #1 of string classes
  使用cast来实现类型转换是不好的做法,除非有文档明确指出这种转换可以使用。
促使我写这两篇文章的原因是字符串类型转换中经常遇到的一些问题。当我们使用cast把字符串从类型X转换到类型Z的时候,我们不知道为什么代码不能正常 工作。各种各样的字符串类型,尤其是BSTR,几乎没有在任何一个地方的文档中被明确的指出可以用cast来实现类型转换。所以我想一些人可能会使用 cast来实现类型转换并希望这种转换能够正常工作。
  除非源字符串是一个被明确指明支持转换操作符的字符串包装类,否则cast不对字符串做任何转换。对常量字符串使用cast不会起到任何作用,所以下面的代码: 
void SomeFunc ( LPCWSTR widestr );main(){  SomeFunc ( (LPCWSTR) \"C:\\\\foo.txt\" );  // WRONG!}      
肯定会失败。它可以被编译,因为cast操作会撤消编译器的类型检查。但是,编译可以通过并不能说明代码是正确的。
  在下面的例子中,我将会指明cast在什么时候使用是合法的。
C-style strings and typedefs
   正如我在第一部分中提到的,windows APIs 是用TCHARs来定义的,在编译时,它可以根据你是否定义_MBCS或者_UNICODE被编译成MBCS或者Unicode字符。你可以参看第一部分 中对TCHAR的完整描述,这里为了方便,我列出了字符的typedefs
TypeMeaning
WCHARUnicode character (wchar_t)
TCHarmBCS or Unicode character, depending on preprocessor settings
LPSTR string of char (char*)
LPCSTRconstant string of char (const char*)
LPWSTR string of WCHAR (WCHAR*)
LPCWSTR constant string of WCHAR (const WCHAR*)
LPTSTR string of TCHAR (TCHAR*)
LPCTSTR constant string of TCHAR (const TCHAR*)

   一个增加的字符类型是OLETYPE。它表示自动化接口(如word提供的可以使你操作文档的接口)中使用的字符类型。这种类型一般被定义成 wchar_t,然而如果你定义了OLE2ANSI预处理标记,OLECHAR将会被定义成char类型。我知道现在已经没有理由定义OLE2ANSI (从MFC3以后,微软已经不使用它了),所以从现在起我将把OLECHAR当作Unicode字符。
这里给出你将会看到的一些OLECHAR相关的typedefs:
TypeMeaning
OLECHAR Unicode character (wchar_t)
LPOLESTR string of OLECHAR (OLECHAR*)
LPCOLESTR constant string of OLECHAR (const OLECHAR*) [Page]

  还有两个用于包围字符串和字符常量的宏定义,它们可以使同样的代码被用于MBCS和Unicode builds :
Type Meaning
_T(x)Prepends L to the literal in Unicode builds.
OLESTR(x)Prepends L to the literal to make it an LPCOLESTR. 

  在文档或例程中,你还会看到好多_T的变体。有四个等价的宏定义,它们是TEXT, _TEXT, __TEXT和__T,它们都起同样的做用。

 COM 中的字符串 —— BSTR 和 VARIANT

  很多自动化和COM接口使用BSTR来定义字符串。BSTRs中有几个\"陷阱\",所以这里我用单独的部分来说明它。
  BSTR 是 Pascal-style 字符串(字符串长度被明确指出)和C-style字符串(字符串的长度要通过寻找结束符来计算)的混合产物。一个BSTR是一个Unicode字符串,它的长度是预先考虑的,并且它还有一个0字符作为结束标记。下面是一个BSTR的示例:

 
06 00 00 0042 006F 0062 0000 00
--length--BobEOS

   注意字符串的长度是如何被加到字符串数据中的。长度是DWORD类型的,保存了字符串中包含的字节数,但不包括结束标记。在这个例子中,\"Bob\"包含 3个Unicode字符(不包括结束符),总共6个字节。字符串的长度被预先存储好,以便当一个BSTR在进程或者计算机之间被传递时,COM库知道多少 数据需要传送。(另一方面,一个BSTR能够存储任意数据块,而不仅仅是字符,它还可以包含嵌入在数据中的0字符。然而,由于这篇文章的目的,我将不考虑 那些情况)。
  在 C++ 中,一个 BSTR 实际上就是一个指向字符串中第一个字符的指针。它的定义如下: 
BSTR bstr = NULL;  bstr = SysAllocString ( L\"Hi Bob!\" );   if ( NULL == bstr )    // out of memory error   // Use bstr here... SysFreeString ( bstr );      
自然的,各种各样的BSTR封装类为你实现内存管理。
  另外一个用在自动化接口中的变量类型是VARIANT。它被用来在无类型(typeless)语言,如Jscript和VBScript,来传递数 据。一个VARIANT可能含有很多不同类型的数据,例如long和IDispatch*。当一个VARIANT包含一个字符串,字符串被存成一个 BSTR。当我后面讲到VARIANT封装类时,我会对VARIANT多些介绍。

 字符串封装类

  到目前为止,我已经介绍了各种各样的字符串。下面,我将说明封装类。对于每个封装类,我将展示怎样创建一个对象及怎样把它转换成一个C语言风格的字符 串指针。C语言风格的字符串指针对于API的调用,或者创建一个不同的字符串类对象经常是必需的。我不会介绍字符串类提供的其他操作,比如排序和比较。
  重复一遍,除非你确切的明白结果代码将会做什么,否则不要盲目地使用cast来实现类型转换。

 CRT提供的类

_bstr_t
  _bstr_t是一个对BSTR的完整封装类,实际上它隐藏了底层的BSTR。它提供各种构造函数和操作符来访问底层的C语言风格的字符串。然而, _bstr_t却没有访问BSTR本身的操作符,所以一个_bstr_t类型的字符串不能被作为输出参数传给一个COM方法。如果你需要一个BSTR*参 数,使用ATL类CComBSTR是比较容易的方式。

共5页 首页 上一页 1 2 3 4 5 下一页 尾页 跳转到
相关内容
赞助商链接