在软件开发中,字符串处理是一个常见且关键的任务。标准C++库提供了一个强大的字符串模板——basic_string<>,
但有时它的使用并不那么直观。与此同时,MFC(Microsoft Foundation Classes)的CString类以其易用性而受到许多开发者的喜爱。
它能够检查空指针,隐式转换为const TCHAR*,并且提供了一些非常实用的成员函数(如Format、Load等),
使得字符串编程变得轻松。然而,不想继续使用MFC,也不想依赖任何专有库,因为需要可移植性。
因此,决定将两者的优点结合起来,创建了CStdString。这是一个从basic_string<TCHAR>派生的类(实际上是模板实例化)。
它为basic_string增加了整个CString API。得到了CString的易用性,同时保持了100%的basic_string兼容性。
简而言之,一个CStdString对象是一个basic_string,它在极少数情况下(下面会提到)也是一个CString的直接替代品。
最美妙的是,这两个API(basic_string和CString)都是众所周知且有良好文档记录的。
最初,几年前将这篇文章提交给了另一个代码网站(这里就不提名字了)。非常喜欢CodeProject,所以也想在这里提交。
在过去的4年里,几乎在每一个专业项目中都使用了这个类。它被证明是写过的最有用的代码之一。它也经过了广泛的调试。
如果喜欢它,或者有任何问题,请通过电子邮件联系。很乐意帮忙。
在这里提供了一个简单的源应用程序来证明一些CString函数的工作,但这真的只是一个象征。
使用CString和/或basic_string的示例项目列表是巨大的。
CString的直接替代品(见下面的例外情况)。
始终提供两种实例化版本——基于wchar_t的版本CStdStringW和基于char的版本CStdStringA。
名称CStdString只是一个这些两者之一的typedef。
在所有函数中安全检查NULL字符串指针输入(类似于CString)。
额外的构造函数和赋值操作符,可以自动在宽(基于wchar_t)和窄(基于char)字符串之间进行转换。
隐式转换为c_str()。C++委员会可能不喜欢这个,但确实喜欢。
在多个平台上构建,包括Windows、Unix和Linux。与多个标准C++库实现兼容,包括Dinkumware、GNU、CodeWarrior和STLPort。
Win32构建为提供了一些额外的好处,比如UNICODE/MBCS转换宏(就像MFCs)以及用于将CStdString对象持久化到和从DCOM IStreams的成员函数。
不使用基类模板basic_string的任何实现细节。
派生的模板不向basic_string添加任何成员数据,也不添加任何虚拟函数。
未能完全复制CString API。有两个函数CString和basic_string都有,但实现方式不同。
在这些情况下,认为最好让CStdString表现得像basic_string(基类)而不是CString。具体来说,
CStdString::operator[]按值返回字符(与CString按引用返回它们不同)。
接受一个字符和一个计数的构造函数的顺序是(计数,值),这与CString声明的顺序相反。这是basic_string<>需要的顺序,
而且不可能同时实现两个版本。
还有两个CString函数根本无法实现——LockBuffer和UnlockBuffer。
basic_string<>派生
写的模板是从basic_string派生的,这是一个没有虚析构函数的类模板。任何C++的入门文本都会告诉,
从没有虚析构函数的类派生是危险的。它可能导致未定义的行为。所以,如果要编写以下代码(通过基类指针删除CStdStringA),
从技术上讲,会得到未定义的行为:
C++
// assign DERIVED object to BASE pointer
std::string *pstr = new CStdStringA("Hi");
// delete DERIVED through BASE class pointer -- UNDEFINED
delete pstr;