Using the CString Class
The MFC CString class is a significant de facto extension of the C++ language. The CString class has many useful operators and member functions, but perhaps its most important feature is its dynamic memory allocation. You never have to worry about the size of a CString object. The following statements represent typical uses of CString objects:
CString strFirstName("Elvis");
CString strLastName("Presley");
CString strTruth = strFirstName + " " + strLastName; // concatenation
strTruth += " is alive";
ASSERT(strTruth == "Elvis Presley is alive");
ASSERT(strTruth.Left(5) == strFirstName);
ASSERT(strTruth[2] == 'v'); // subscript operator
In a perfect world, C++ programs would use all CString objects and never use ordinary zero-terminated character arrays. Unfortunately, many runtime library functions still use character arrays, so programs must always mix and match their string representations. Fortunately, the CString class provides a const char*() operator that converts a CString object to a character pointer. Many of the MFC library functions have const char* parameters. Take the global AfxMessageBox function, for example. Here is one of the function's prototypes:
int AFXAPI AfxMessageBox(LPCTSTR lpszText, UINT nType = MB_OK,
UINT nIDHelp = 0);
Note that LPCTSTR is not a pointer to a CString object but is a Unicode-enabled replacement for const char*.You can call AfxMessageBox in this way
char szMessageText[] = "Unknown error";
AfxMessageBox(szMessageText);
or this way:
CString strMessageText("Unknown error");
AfxMessageBox(strMessageText);
Now suppose you want to generate a formatted string. CString::Format does the job, as shown here:
int nError = 23;
CString strMessageText;
strMessageText.Format("Error number %d", nError);
AfxMessageBox(strMessageText);
Note | Suppose you want direct write access to the characters in a CString object. If you write code like this: CString strTest("test"); you'll get a compile error because the first parameter of strncpy is declared char*, not const char*. The CString::GetBuffer function "locks down" the buffer with a specified size and returns a char*. You must call the ReleaseBuffer member function later to make the string dynamic again. The correct way to capitalize the T is shown in the following example. CString strTest("test"); |
The const char* operator takes care of converting a CString object to a constant character pointer, but what about conversion in the other direction? It so happens that the CString class has a constructor that converts a constant character pointer to a CString object, and it has a set of overloaded operators for these pointers. That's why statements such as the following work:
strTruth += " is alive";
The special constructor works with functions that take a CString reference parameter, such as CDC::TextOut. In the following statement, a temporary CString object is created on the calling program's stack and then the object's address is passed to TextOut:
pDC->TextOut(0, 0, "Hello, world!");
It's more efficient to use the other overloaded version of CDC::TextOut if you're willing to count the characters:
pDC->TextOut(0, 0, "Hello, world!", 13);
If you're writing a function that takes a string parameter, you've got some design choices. Here are some programming rules:
If the function doesn't change the contents of the string and you're willing to use C runtime functions such as strncpy, use a const char* parameter.
If the function doesn't change the contents of the string but you want to use CString member functions inside the function, use a const CString& parameter.
If the function changes the contents of the string, use a CString& parameter.