在软件开发中,字符串处理是一个常见且关键的任务。标准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 IStream
s的成员函数。
不使用基类模板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;