The MFC CString class is a significant de facto extension to the C++ language. As the Microsoft Foundation Classes and Templates section of the online help points out, 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 statements here 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: LPCTSTR is not a pointer to a CString object but rather is a Unicode-enabled replacement for const char*.)
You can call AfxMessageBox this way:
char szMessageText[] = "Unknown error"; AfxMessageBox(szMessageText);
or you can call it 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);
Suppose you want direct write access to the characters in a CString object. If you write code like this:
CString strTest("test"); strncpy(strTest, "T", 1);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 here.
CString strTest("test"); strncpy(strTest.GetBuffer(5), "T", 1); strTest.ReleaseBuffer(); ASSERT(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.