Fully guided by C ++ strings 3-string encapsulation class continuation

Source: Internet
Author: User
MFC class

Cstring
Because an object of the MFC cstring class contains tchar characters, the exact character type depends on the pre-processing symbol you define. Generally speaking, cstring is similar to STL string, which means you must treat it as an opaque object. You can only use the method provided by cstring to modify the cstring object. Cstring has the advantage that a string does not have: cstring has the constructor that receives both MBCS and Unicode strings, and it also has an lpctstr conversion character, therefore, you can pass the cstring object directly to a function that receives the lpctstr without calling the c_str () function.

// ConstructingCString s1 = "char string";  // construct from a LPCSTRCString s2 = L"wide char string";  // construct from a LPCWSTRCString s3 ( '' '', 100 );  // pre-allocate a 100-byte buffer, fill with spacesCString s4 = "New window text";   // You can pass a CString in place of an LPCTSTR:  SetWindowText ( hwndSomeWindow, s4 );   // Or, equivalently, explicitly cast the CString:  SetWindowText ( hwndSomeWindow, (LPCTSTR) s4 );        

You can load a string from your string table. A cstring constructor and loadstring () function can complete it. The format () method can read a string with a certain format from the string table at will.

// Constructing/loading from string tableCString s5 ( (LPCTSTR) IDS_SOME_STR );  // load from string tableCString s6, s7;   // Load from string table.  s6.LoadString ( IDS_SOME_STR );   // Load printf-style format string from the string table:  s7.Format ( IDS_SOME_FORMAT, "bob", nSomeStuff, ... );  

The first constructor looks a bit strange, but this is actually the method described in the document for loading a string. Note that for a cstring variable, the only valid conversion character you can use is lpctstr. Converting to lptstr is incorrect. The habit of converting a cstring variable into lptstr will hurt you, because when your program crashes, you may not know why, because you use the same code everywhere and they happen to work normally at that time. Call the getbuffer () method to obtain a very large pointer to the buffer. The following is an example of correct usage. This code is used to set text for items in a list control:

CString str = _T("new text");LVITEM item = {0};  item.mask = LVIF_TEXT;  item.iItem = 1;  item.pszText = (LPTSTR)(LPCTSTR) str; // WRONG!  item.pszText = str.GetBuffer(0);      // correct   ListView_SetItem ( &item );str.ReleaseBuffer();  // return control of the buffer to str      

The psztext member is an lptstr variable and a very large pointer. Therefore, you need to call getbuffer () for Str (). The getbuffer () parameter is the minimum length that you need cstring to allocate to the buffer. For some reason, you need a modifiable buffer to store 1 K tchars. You need to call getbuffer (1024 ). When 0 is used as a parameter, getbuffer () returns a pointer to the current content of the string.
The preceding underlined statement can be compiled. In this case, it can even work normally. But this does not mean that this line of code is correct. By using extraordinary conversions, you have destroyed the object-oriented encapsulation and made some assumptions about the internal implementation of cstring. If you have this conversion habit, you will eventually fall into a code crash. You may wonder why the Code cannot work normally, because you use the same code everywhere and the code looks correct.
Do you know how many software bugs people complain about? The bug in the software is caused by Incorrect code written by the programmer. Do you really want to write some code that you know is wrong to contribute to the recognition that all software is full of bugs? Take some time to learn how to use cstring to make your code work normally at any time.
Cstring has two functions to create a BSTR from a cstring. They are allocsysstring () and setsysstring ().

// Converting to BSTRCString s5 = "Bob!";BSTR bs1 = NULL, bs2 = NULL;  bs1 = s5.AllocSysString();  s5.SetSysString ( &bs2 );  SysFreeString ( bs1 );  SysFreeString ( bs2 );      

Colevariant
Colevariant is similar to ccomvariant. Colevariant inherits from variant, so it can be passed to the function that receives variant. Unlike ccomvariant, colevariant only has one lpctstr constructor. There is no constructor for the lpcstr and lpcwstr. In most cases, this is not a problem, because your string may be the lpctstrs in any case, but this is a problem to be aware. Colevariant also has a constructor that receives cstring parameters.

// ConstructingCString s1 = _T("tchar string");COleVariant v1 = _T("Bob"); // construct from an LPCTSTRCOleVariant v2 = s1; // copy from a CString      

Like ccomvariant, you must directly access variant members. To convert variant into a string, you should use the changetype () method. However, colevariant: changetype () throws an exception if it fails, instead of returning an hresult code that indicates a failure.

// Extracting dataCOleVariant v3 = ...; // fill in v3 from somewhereBSTR bs = NULL;  try    {    v3.ChangeType ( VT_BSTR );    bs = v3.bstrVal;    }  catch ( COleException* e )    {    // error, couldn''t convert    }  SysFreeString ( bs );      

 Wtl class

Cstring
The cstring behavior of wtl is exactly the same as that of MFC cstring, so you can refer to the above section on the cstring of MFC.

 CLR and VC 7

System: string is a. Net class used to process strings. Internally, A String object contains an unchangeable string sequence. Any operation on the string object actually returns a New String object, because the original object cannot be changed. One feature of string is that if you have more than one string object that contains the same character sequence, they actually point to the same object. Compared with the use extension of C ++, A New String constant prefix S is added, and S is used to represent a controlled String constant (a managed string literal ).

// ConstructingString* ms = S"This is a nice managed string";      

You can pass an uncontrolled string to create a String object, but this may cause a slight loss in efficiency compared to using a controlled string to create a String object. This is because all string instances with the same prefix of S represent the same object, but this is not applicable to uncontrolled objects. The following code clearly clarifies this point:

String* ms1 = S"this is nice";String* ms2 = S"this is nice";String* ms3 = L"this is nice";  Console::WriteLine ( ms1 == ms2 ); // prints true  Console::WriteLine ( ms1 == ms3);  // prints false      

The correct method for comparing strings that may not use the S prefix is to use string: compareto ()

  Console::WriteLine ( ms1->CompareTo(ms2) );  Console::WriteLine ( ms1->CompareTo(ms3) );      

The above two lines of code print 0, indicating that the two strings are equal. String and MFC 7 cstring are easily converted. Cstring has a conversion operation to lpctstr, while string has two constructors that receive char * And wchar_t *. Therefore, you can directly pass a cstring variable to a string constructor.

CString s1 ( "hello world" );String* s2 ( s1 );  // copy from a CString      

The inverse direction conversion is similar.

String* s1 = S"Three cats";CString s2 ( s1 );      

This may confuse you, but it does work. Since vs. net, cstring has a constructor that receives string objects.

  CStringT ( System::String* pString );      

For some quick operations, you may want to access the underlying string:

String* s1 = S"Three cats";  Console::WriteLine ( s1 );const __wchar_t __pin* pstr = PtrToStringChars(s1);  for ( int i = 0; i < wcslen(pstr); i++ )    (*const_cast<__wchar_t*>(pstr+i))++;  Console::WriteLine ( s1 );      

Ptrtostringchars () returns a const _ wchar_t * pointing to the underlying string. we need to fix it. Otherwise, the Garbage Collector may move it when we are managing its content.

 Use string classes in printf-style format functions

When using string encapsulation classes in printf () or similar functions, you must be very careful. These functions include sprintf () and its variants, as well as trace and atltrace macros. Because these functions do not check the type of added parameters, you must be careful that they can only be passed to their C-style string pointers, rather than a complete string class.
For example, to pass a _ bstr_t string to atltrace (), you must use an explicit conversion (lpcstr) or (lpcwstr ):

_bstr_t bs = L"Bob!";ATLTRACE("The string is: %s in line %d/n", (LPCSTR) bs, nLine);

If you forget to use the transform character and pass the entire _ bstr_t object to the function, some meaningless output will be displayed, because all internal data saved by _ bstr_t will be output.

 Summary of all classes

A common conversion method between two string classes is to convert the source string into a C-language string pointer, and then pass the pointer to the constructor of the target type. The following table shows how to convert a string into a C-language string pointer and which classes have constructor functions that receive C-language string pointers.

Class String type Convert to char *? Convert to const char *? Convert to wchar_t *? Convert to const wchar_t *? Convert to BSTR? Construct from char *? Construct from wchar_t *?
_ Bstr_t BSTR Yes cast1 Yes cast Yes cast 1 Yes cast YES2 Yes Yes
_ Variant_t BSTR No No No Cast
_ Bstr_t3
Cast
_ Bstr_t3
Yes Yes
String MBCS No Yes c_str () method No No No Yes No
Wstring Unicode No No No Yes c_str () method No No Yes
Ccombstr BSTR No No No Yes cast to BSTR Yes cast Yes Yes
Ccomvariant BSTR No No No Yes4 Yes 4 Yes Yes
Cstring Tchar No6 In MBCS
Builds, cast
No 6 In Unicode
Builds, cast
No5 Yes Yes
Colevariant BSTR No No No Yes 4 Yes 4 In MBCS
Builds
In Unicode
Builds
  • 1. Even if _ bstr_t provides a conversion operator to a very large number of pointers, modifying the underlying buffer will also cause GPF if you overflow the buffer or cause memory leakage.
  • 2 , _ Bstr_t internally uses a wchar_t * To save BSTR, so you can use const wchar_t * to access BSTR. This is an implementation detail. You can use it with caution and this detail may change in the future.
  • 3 If the data cannot be converted to BSTR, an exception is thrown.
  • 4 , Use changetype (), and then access the bstrval member of variant. In MFC, if the data conversion fails, an exception is thrown.
  • 5 The BSTR function is not converted here. However, allocsysstring () returns a new BSTR.
  • 6 Using the getbuffer () method, you can get a very large number of tchar pointers temporarily.
  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.