# ftsItem_content

c0Title: Working with Crypto API to encrypt/decrypt text
c1Code:
This article uses the CRYPTOAPI sample application to demonstrate how to decrypt or encrypt data.

For more information check MSDN article 

MSDN Article : The Cryptography API, or How to Keep a Secret

Here is the basic steps to encrypt/decrypt data using Crypto APIs

[Step-1] Initiating the Cryptography Service Provider (CSP): CryptAcquireContext, CryptReleaseContext The CryptAcquireContext function is used to obtain a handle to a particular key container within a particular CSP. This returned handle can then be used to make calls to the selected CSP. 

At the end of encryption/decryption you can call the CryptReleaseContext function to release the handle returned from a call to CryptAcquireContext.

[Step-2] Hashing Data: CryptCreateHash, CryptHashData, CryptGetHashParam, and CryptDestroyHash "hashing" or "hash," refers to the method or algorithm used to derive a numeric value from a piece of data. In our case we will derive a numeric value (Hash) from our password which will be used to encrypt/decrypt the data and then this Hash value will be used to generate session key which we will see in the next step.

To get hash value from Password first create a hash object using CryptCreateHash then you can call CryptHashData to get hash value derived from your password.

[Step-3] Generating Keys: CryptDeriveKey, CryptGenKey, CryptDestroyKey These three functions are the ones used to generate handles to keys: 

The CryptDeriveKey function is used to generate a key from a specified password. 

The CryptGenKey function is used to generate a key from random generated data. 

The CryptDestroyKey function is used to release the handle to the key object. 

[Step-4] Encrypting and Decrypting Data: CryptEncrypt, CryptDecrypt In this step you prepare Buffer for Plain text or Cipher text (Encrypted text) for CryptEncrypt/CryptDecrypt call and then you can call CryptEncrypt for encryption or CryptDecrypt for decryption.

[Step-5] Cleanup : CryptDestroyKey, CryptDestroyHash, CryptReleaseContext Once you are done with encryption/decryption you have to do cleanup of resources taken by Crypto Apis. Cleanup requires the following steps
- Destroy session key using CryptDestroyKey
- Destroy key exchange key handle using CryptDestroyKey
- Destroy hash object using CryptDestroyHash
- Release Context provider handle using CryptReleaseContext

Step-By-Step Example

- Create a standard exe project
- Add three textbox controls and one command button control on the form1. Set Multine=True for Text1 and Text2
- Add the following code in form1 

 Click here to copy the following block Private Const CRYPT_NEWKEYSET = &H8

Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" ( _
    phProv As Long, pszContainer As String, pszProvider As String, _
    ByVal dwProvType As Long, ByVal dwFlags As Long) As Long

Private Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, _
    ByVal Algid As Long, ByVal hKey As Long, ByVal dwFlags As Long, phHash As Long) As Long

Private Declare Function CryptHashData Lib "advapi32.dll" (ByVal hHash As Long, _
    ByVal pbData As String, ByVal dwDataLen As Long, ByVal dwFlags As Long) As Long

Private Declare Function CryptDeriveKey Lib "advapi32.dll" ( _
    ByVal hProv As Long, ByVal Algid As Long, ByVal hBaseData As Long, ByVal dwFlags As Long, _
    phKey As Long) As Long

Private Declare Function CryptDestroyHash Lib "advapi32.dll" (ByVal hHash As Long) As Long

Private Declare Function CryptDestroyKey Lib "advapi32.dll" (ByVal hKey As Long) As Long

Private Declare Function CryptEncrypt Lib "advapi32.dll" (ByVal hKey As Long, _
    ByVal hHash As Long, ByVal Final As Long, ByVal dwFlags As Long, ByVal pbData As String, _
    pdwDataLen As Long, ByVal dwBufLen As Long) As Long

Private Declare Function CryptDecrypt Lib "advapi32.dll" (ByVal hKey As Long, _
    ByVal hHash As Long, ByVal Final As Long, ByVal dwFlags As Long, ByVal pbData As String, _
    pdwDataLen As Long) As Long

Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, _
    ByVal dwFlags As Long) As Long

Private Declare Function GetLastError Lib "kernel32" () As Long

'constants for Cryptography API functions Private Const MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
Private Const PROV_RSA_FULL = 1
Private Const ALG_CLASS_DATA_ENCRYPT = 24576 Private Const ALG_CLASS_HASH = 32768

Private Const ALG_TYPE_ANY = 0
Private Const ALG_TYPE_BLOCK = 1536
Private Const ALG_TYPE_STREAM = 2048

Private Const ALG_SID_RC2 = 2

Private Const ALG_SID_RC4 = 1
Private Const ALG_SID_MD5 = 3
Private Const CALG_MD5 = ((ALG_CLASS_HASH Or ALG_TYPE_ANY) Or ALG_SID_MD5) Private Const CALG_RC2 = ((ALG_CLASS_DATA_ENCRYPT Or ALG_TYPE_BLOCK) Or ALG_SID_RC2) Private Const CALG_RC4 = ((ALG_CLASS_DATA_ENCRYPT Or ALG_TYPE_STREAM) Or ALG_SID_RC4)

Private Const ENCRYPT_ALGORITHM = CALG_RC4 Private Const ENCRYPT_BLOCK_SIZE = 1

Private Const CRYPT_EXPORTABLE = 1

Public Function DoCryptoEncrypt(sPassword As String, PlainText As String) As String

  Dim lHHash As Long
  Dim lHkey As Long
  Dim lResult As Long
  Dim lHExchgKey As Long
  Dim lHCryptprov As Long

  Dim sContainer As String
  Dim lCryptLength As Long
  Dim lCryptBufLen As Long
  Dim sCryptBuffer As String

  On Error GoTo EncryptError

  Dim sOutputBuffer As String

  Dim sProvider

  'Get handle to the default CSP
  sProvider = MS_DEF_PROV & vbNullChar
  
  If Len(PlainText) = 0 Then
    DoCryptoEncrypt = ""
    Exit Function
  End If

  sOutputBuffer = ""

  If Not CBool(CryptAcquireContext(lHCryptprov, ByVal _
      sContainer, ByVal sProvider, PROV_RSA_FULL, 0)) Then
    ' If there is no default key container then create one
    ' using Flags field
    If GetLastError = 0 Then
      If Not CBool(CryptAcquireContext(lHCryptprov, 0&, ByVal sProvider, PROV_RSA_FULL, CRYPT_NEWKEYSET)) Then
        sOutputBuffer = PlainText
        GoTo Finished
      End If
    End If
  End If

  'Create a hash object
  If Not CBool(CryptCreateHash(lHCryptprov, CALG_MD5, 0, _
      0, lHHash)) Then
    MsgBox ("Error " & CStr(GetLastError) & _
        " during CryptCreateHash!")
    GoTo Finished
  End If

  'Hash in the password text
  If Not CBool(CryptHashData(lHHash, sPassword, _
      Len(sPassword), 0)) Then
    MsgBox ("Error " & CStr(GetLastError) & _
        " during CryptHashData!")
    GoTo Finished
  End If

  'Create a session key from the hash object.
  If Not CBool(CryptDeriveKey(lHCryptprov, _
      ENCRYPT_ALGORITHM, lHHash, 0, lHkey)) Then
    MsgBox ("Error " & CStr(GetLastError) & _
        " during CryptDeriveKey!")
    GoTo Finished
  End If

  'Destroy the hash object.
  CryptDestroyHash (lHHash)
  lHHash = 0

  'Create a buffer for the CryptEncrypt function
  lCryptLength = Len(PlainText)
  lCryptBufLen = lCryptLength * 2
  sCryptBuffer = String(lCryptBufLen, vbNullChar)
  LSet sCryptBuffer = PlainText

  'Encrypt the text data
  If Not CBool(CryptEncrypt(lHkey, 0, 1, 0, sCryptBuffer, _
      lCryptLength, lCryptBufLen)) Then
    MsgBox ("bytes required:" & CStr(lCryptLength))
    MsgBox ("Error " & CStr(GetLastError) & _
        " during CryptEncrypt!")
  End If

  sOutputBuffer = Mid$(sCryptBuffer, 1, lCryptLength)

Finished:
  'Outa here
  DoCryptoEncrypt = sOutputBuffer

  'Destroy session key.
  If (lHkey) Then lResult = CryptDestroyKey(lHkey)

  'Destroy key exchange key handle
  If lHExchgKey Then CryptDestroyKey (lHExchgKey)

  'Destroy hash object
  If lHHash Then CryptDestroyHash (lHHash)

  'Release Context provider handle
  If lHCryptprov Then lResult = _
      CryptReleaseContext(lHCryptprov, 0)

  Exit Function

EncryptError:

  MsgBox ("Encrypt Error: " & Error$)

  GoTo Finished

End Function


Public Function DoCryptoDecrypt(sPassword As String, CryptText As String) As String

  Dim lHExchgKey As Long
  Dim lHCryptprov As Long
  Dim lHHash As Long
  Dim lHkey As Long
  Dim lResult As Long

  Dim sContainer As String
  Dim sProvider As String

  Dim sCryptBuffer As String
  Dim lCryptBufLen As Long
  Dim lCryptPoint As Long

  Dim lPasswordPoint As Long
  Dim lPasswordCount As Long

  Dim sOutputBuffer As String

  On Error GoTo DecryptError


  If Len(CryptText) = 0 Then
    DoCryptoDecrypt = ""
    Exit Function
  End If
  'Clear the Output buffer
  sOutputBuffer = ""

  'Get handle to the default CSP.
  sContainer = vbNullChar
  sProvider = vbNullChar
  sProvider = MS_DEF_PROV & vbNullChar
  If Not CBool(CryptAcquireContext(lHCryptprov, ByVal sContainer, ByVal sProvider, PROV_RSA_FULL, 0)) Then
    If Not CBool(CryptAcquireContext(lHCryptprov, ByVal sContainer, ByVal sProvider, PROV_RSA_FULL, CRYPT_NEWKEYSET)) Then
      'MsgBox ("Error " & CStr(GetLastError) & " during CryptAcquireContext! ")"
      sOutputBuffer = CryptText
      GoTo Finished
    End If
  End If

  'Create a hash object
  If Not CBool(CryptCreateHash(lHCryptprov, CALG_MD5, 0, 0, lHHash)) Then
    MsgBox ("Error " & CStr(GetLastError) & " during CryptCreateHash! ")
    GoTo Finished
  End If

  'Hash in the password text
  If Not CBool(CryptHashData(lHHash, sPassword, Len(sPassword), 0)) Then
    MsgBox ("Error " & CStr(GetLastError) & " during CryptHashData!")
    GoTo Finished
  End If

  'Create a session key from the hash object
  If Not CBool(CryptDeriveKey(lHCryptprov, ENCRYPT_ALGORITHM, lHHash, 0, lHkey)) Then
    MsgBox ("Error " & CStr(GetLastError) & " during CryptDeriveKey!")
    GoTo Finished
  End If

  'Destroy the hash object.
  CryptDestroyHash (lHHash)
  lHHash = 0

  'Prepare sCryptBuffer for CryptDecrypt
  lCryptBufLen = Len(CryptText) * 2
  sCryptBuffer = String(lCryptBufLen, vbNullChar)
  LSet sCryptBuffer = CryptText

  'Decrypt data
  If Not CBool(CryptDecrypt(lHkey, 0, 1, 0, sCryptBuffer, lCryptBufLen)) Then
    MsgBox ("bytes required:" & CStr(lCryptBufLen))
    MsgBox ("Error " & CStr(GetLastError) & " during CryptDecrypt!")
    GoTo Finished
  End If

  'Setup output buffer with just decrypted data
  sOutputBuffer = Mid$(sCryptBuffer, 1, lCryptBufLen / 2)

Finished:
  'Outa here
  DoCryptoDecrypt = sOutputBuffer

  'Destroy session key
  If (lHkey) Then lResult = CryptDestroyKey(lHkey)

  'Destroy key exchange key handle
  If lHExchgKey Then CryptDestroyKey (lHExchgKey)

  'Destroy hash object
  If lHHash Then CryptDestroyHash (lHHash)

  'Release Context provider handle
  If lHCryptprov Then lResult = CryptReleaseContext(lHCryptprov, 0)

  Exit Function

DecryptError:
  MsgBox ("Decrypt Error: " & Error$)
  GoTo Finished
End Function

Private Sub Command1_Click()
  Dim MyEncryptedMsg As String
  Dim MyKey As String
  Dim MyClearTextMsg As String
  Dim MyClearTextMsgBackAgain As String

  MyKey = Text3

  If Command1.Caption = "Encrypt Message" Then
    '//Encrypt
    MyClearTextMsg = Text1
    MyEncryptedMsg = DoCryptoEncrypt(MyKey, MyClearTextMsg)
    Command1.Caption = "Decrypt Message"
    Text2 = MyEncryptedMsg
  Else
    '//Decrypt
    MyEncryptedMsg = Text2
    MyClearTextMsgBackAgain = DoCryptoDecrypt(MyKey, MyEncryptedMsg)
    Command1.Caption = "Encrypt Message"
    Text2 = MyClearTextMsgBackAgain
  End If
End Sub

Private Sub Form_Load()
  '//Some text which we want to encrypt
  Text1 = "Our mission time is 9.00 PM" & vbCrLf & _
      "Mission Code : ROYALBLUE-1" & vbCrLf & _
      "Main Gate Password : 22789001"

  Text3 = "MYSECRETPASS123"  '//This is secrete key which will be used to encrypt/decrypt our message
  Command1.Caption = "Encrypt Message"
End Sub 


c0Title: Wrap I/O for Text Files
c1Code:
In a production application, every time you want to access a file for reading or writing, you must retrieve a free handle using the FreeFile() function to ensure you don�t overwrite an existing handle. You also must remember to close the file after you finish with it. In some cases, you can avoid the trouble by encasing this functionality inside utility functions. For example, I wrote these two functions to go between strings and text files in my apps:

 

Public Function ReadFile(FileName As String) As String

       Dim hFile As Integer

       hFile = FreeFile

       On Error GoTo ErrorTrap

             Open FileName For Input As #hFile

             ReadFile = Input(LOF(hFile), hFile)

             Close # hFile

       Exit Function

ErrorTrap:

       ReadFile = ""

End Function

Public Sub WriteFile(FileName As String, Contents As _
       String)

       Dim hFile As Integer

       hFile = FreeFile

       On Error Resume Next

       Open FileName For Output As #hFile

       Print #hFile, Contents;

       Close #hFile

End Sub

 

Once you put these functions in your project, you can read and write text files quickly. For example, here�s a way you might use these functions to copy text files:

 

Call WriteFile("c:\b.txt", ReadFile("c:\a.txt"))

�Konstantin Komissarchik, Brier, Washington


c0Title: Write an IsTime Function
c1Code:
Use this function to determine whether a string represents a valid time: 

 

Public Function IsTime(sTimeArg As String) As Boolean

       IsTime = IsDate(Format(Date, "short date") & _

             " " & sTimeArg)

End Function

�Geir Villmones, Mosj�en, Norway


c0Title: You can use the For Each/Next syntax for simple arrays
c1Code:
For example:
Private Sub Form_Load()
Dim sum As String
Dim x As Variant
Dim a(10) As Variant
   a(1) = "A"
   a(2) = "B"
   a(3) = "C"
   a(4) = "D"

   For Each x In a
	sum = sum & x
   Next

   MsgBox sum
End Sub


c0Title: (The Joy of) Memory Mapping
c1Code:
by Andy Harding 


     Q. Streamline Your File I/O 
Is there a fast and easy way to open a file and examine its contents? 
What you need:
Visual C++ 6.0
Windows 98, NT 4.0, 
CE 2.0, or later  
 
A. Try memory mapping your input files. It speeds up file reading and reduces the number of memory allocations that take place in your file I/O. 

When you ask the operating system to map a file into memory, there are several issues to take into account. The first is the level of access you want to have. Memory mapping allows you to read, write, and share data mapped to memory. You'll need to decide which method serves your needs best. The code I've included to help you make this decision provides exclusive, read-only access to the file you're mapping. 

The second issue is the file size. Is the file so large you should consider paging it in separate pieces? Consider the memory available vs. the file's size to determine if you'll need to break up the file, and try different setups to see how they perform. The code asks the operating system to map the entire file into memory. Obviously, this requires enough available memory to hold the file. For this reason, the code I reference here and the code in the listings should be used only with smaller files (see Listings 1 and 2). The sample code uses Win32 API calls, so you can adapt it to almost any programming situation and Windows operating system. I tested this code with Windows 98, NT 4.0, and CE 2.0-2.12. With a little effort, you can extend these examples to provide read and write access, share the mapping between processes, and address concerns when working with large files. 

You use three functions to open a file and map it into memory: CreateFile(), CreateFileMapping(), and MapViewOfFile(). Use CreateFile() in its most basic form to open an existing file as read-only with exclusive access: 



HANDLE hCreateFile = 
   ::CreateFile(
   lpFileName, GENERIC_READ, 0, 
   NULL, OPEN_EXISTING,    
   FILE_ATTRIBUTE_NORMAL, NULL);

It's important to check for a failed attempt to create the file by comparing the return value against INVALID_HANDLE_VALUE, not NULL. (But you already knew that.) 

The CreateFileMapping() function requires the handle to the opened file along with security attributes, a protection flag, two size values, and a name. You don't need to worry about security at this point, so use a NULL for the security attributes. As I mentioned earlier, this example requests read-only memory access. You'll want to read in the entire file, so pass in zero for the high order size and zero for the low order size. You might think this would result in an empty buffer, but the zeros let CreateFileMapping() know you want to get the entire file. The last argument in CreateFileMapping() is a name for the mapping used to share the mapping between processes. You want exclusive access, so set this parameter to NULL. This effectively eliminates another process from using this mapping: 



HANDLE hCreateMapping = 
   ::CreateFileMapping 
   (m_hCreateFile, 
   NULL, PAGE_READONLY, 0, 0, NULL);

One trick here: CreateFileMapping() returns NULL if the operation fails, not INVALID_HANDLE_VALUE. That's to keep us on our toes�if programming were easy, anyone could do it. 

If you want to share the handle to the memory-mapped file, use OpenFileMapping() from your other process, pass in the name, and boom�you have shared data. MFC provides an excellent class for sharing data between processes: the CMemFile class. However, that's a topic for another time (see Resources). 

The last function call, MapViewOfFile(), provides you with a pointer to the data. The first item in the function is the handle from CreateFileMapping(). You pass the function's offsets into the file along with the amount of data to map. You'll want to map the entire file into your process memory, so use zero for both the high order offset and the low order offset. Also use zero for the size. You use the same logic as you do for the size for CreateFileMapping(); it might seem strange, but it's easier than entering the file size every time the function is called: 



LPBYTE lpFileData = (LPBYTE) 
   MapViewOfFile (m_hCreateMapping,
   FILE_MAP_READ, 0, 0, 0);

You now have a pointer to the file's data and can jump around and read to your heart's content. Closing the file is fairly straightforward: Close every function you've opened. Although the help files say the order isn't important, it's better to be safe than sorry, so close them in reverse order: 



UnmapViewOfFile (lpFileData);
CloseHandle (hCreateMapping);
CloseHandle (hCreateFile);

This code appears rather messy and repetitive. You want to be able to simply open the file and look at its contents; why should you have to call all these functions with the myriad of checks required? The easy answer: to hide the complexity in a class called CROMemMap, for the Read-Only Memory Mapped File. First, define the CROMemMap class (see Listing 1), which encapsulates the memory-mapped file functions. Now, you can implement the CROMemMap class (see Listing 2). After doing this, you'll no longer need to call each function in order and add the checking, or clean up! 

Q. Load Bitmaps 
What's the easiest way to load a device-independent bitmap (DIB) from a file to a CBitmap object? The CBitmap class doesn't have supported function members. 


A. First, get the file into memory. (What a great opportunity to use the memory-mapped file class from the last question!) The CROMemMap class easily moves the data from the file into memory, where you can work with it: 



CROMemMap   BmpFile;
BmpFile.Open (_T("picture.bmp"));

Second, convert the data from the file into the HBITMAP format required by the CBitmap class. Do this with the CreateDIBitmap() API function: 



HBITMAP CreateDIBitmap (HDC hdc, 
   CONST BITMAPINFOHEADER *lpbmih, 
   DWORD fdwInit, 
   CONST VOID *lpbInit, 
   CONST BITMAPINFO *lpbmi, 
   UINT fuUsage); 

CreateDIBitmap() takes a handle to the device the bitmap is based on, the data from the device-independent bitmap (DIB), and some flags as arguments. It returns an HBITMAP, which is the handle to the converted DIB. The HDC determines what type of bitmap it is. You want a bitmap you can place on the screen, so use the return value from your CWnd class's GetDC() member function. If you're writing to the Win32 API directly, call ::GetDC(hWnd), which passes in the handle of your current window. 

Now you need to figure out how you pass the DIB data into the function. To do this, you'll need to understand the format of a DIB (see Table 1). The only difference between a DIB in memory and a DIB stored in a file is the BITMAPFILEHEADER. The first item required from the DIB is a pointer to the BITMAPINFOHEADER. To get the address of the BITMAPINFOHEADER, add the size of BITMAPFILEHEADER to the address of the beginning of the file: 



LPBITMAPINFO      lpInfo;

lpInfo = (LPBITMAPINFO) 
   ((DWORD)g_BmpFile.GetDataPtr() + 
   sizeof (BITMAPFILEHEADER));

There's no guarantee that the next structure is a BITMAPINFO structure (see Table 1). There are four different structures that can be the information structure: BITMAPCOREHEADER, BITMAPINFOHEADER, BITMAPV4HEADER, and BITMAPV5HEADER. You use BITMAPCOREHEADER in OS/2 bitmaps only, which aren't supported in this sample. (When was the last time you worked with an OS/2 bitmap?) BITMAPINFOHEADER is the standard Windows bitmap structure. The version 4 and 5 headers were added in Windows 95/NT 4.0 and Windows 98/2000, respectively. Both versions use BITMAPINFOHEADER data items as their beginning point, then add new elements after the end of the original structure. The nice thing about this little situation is that the first member of all these structures is a DWORD that contains the size of the structure stored in the file (see Table 2). Now you can distinguish between the different flavors of header information structures. The non-OS/2 bitmaps should work without any trouble, so you add a quick check: 



if(lpInfo->bmiHeader.biSize ==
   sizeof (BITMAPCOREHEADER))
{   
   g_BmpFile.Close();
   return FALSE;
}

Then, calculate the data's location, fill out the two flags, and call the function: 



lpBits = (LPBYTE) 
   ((DWORD)g_BmpFile.GetDataPtr() +
   lpFileHeader->bfOffBits);

HBITMAP   hBmp; 

hBmp = ::CreateDIBitmap (hdc,
         &lpInfo->bmiHeader, 
         CBM_INIT, 
         lpBits,
         lpInfo,
         DIB_RGB_COLORS);

Now the bitmap is in the right format to transfer to your CBitmap class. You need only the method to finish. Using CBitmap's Attach() method, inherited from CGdiObject, you can set your CBitmap class to the newly converted HBITMAP. Unfortunately, the MFC help files don't clearly show the inherited members and methods. You'll need to check them out yourself: 



CBitmap BitMap;

BitMap.Attach (hBmp);

You might be wondering why Microsoft didn't write this for you. Well, it did�at least partially. The LoadImage() API function provides provisions to load a bitmap from a file and return an HBITMAP. You just need to call the Attach() method of CBitmap: 



CBitmap   Bitmap;

Bitmap.Attach (::LoadImage(NULL, 
      _T("C:\\windows\\setup.bmp"),
      IMAGE_BITMAP,
      0, 0,
      LR_LOADFROMFILE));

This simple implementation is an easy solution to the original question. As always, it's recommended you check for errors. 

I hope that this column helps you in your coding efforts. If you have any questions or comments, please send them to me. 


Andy Harding is a software engineer at BSQUARE Corp. (Nasdaq BSQR), a leading provider of software for developing Windows-powered, intelligent computing devices. When he's not writing, Andy enjoys using function pointers and eating cold pizza for breakfast. Reach him at andyh@bsquare.com


c0Title: 12 Tips for Effective Operator Overloading
c1Code:
Operator overloading can result in clearer code�but only when used correctly. 

by Bill Wagner 


     Beginning C++ programmers, especially those coming to C++ from other languages, wrestle with the concept of operator overloading�they're afraid to change the meaning of built-in operations in the language (see the sidebar, "What is Operator Overloading?," for more information). But overloading your operators can result in clearer code for users of your class. Which would you rather read: "C=A+B" or "C.assign(A.plus(B))"? If you couldn't overload operators, you'd need to use the second form. 
What you need:
Visual C++ 6.0  
 
When considering whether to use this technique, put yourself in the place of the client programmer, the programmer writing code that uses your class. Does having the overloaded operators help or hinder the readability of code using the class? By determining how the client programmer will use your class, you can decide on the proper set of overloaded operators to write. Operators that you don't write for your class can't be called using your class objects. 

The tricky part of overloading an operator isn't writing a function�it's determining when to write it. Each operator has a well-defined meaning. You should write an operator only when your new meaning for the operator is the same as the existing operator. Put yourself in the place of someone reading your code. In most cases, you should overload an operator only when the class type is a conceptual extension of a built-in type for which the operator was designed. For example, it's natural to overload the arithmetic operators for classes that are extended arithmetic types, such as complex or rational numbers: 



Complex c1( 1.0, -4.0 );
Complex c2( 15.0, 1.0 );
Complex c3 = c1 * c2;
c2 *= c1;

A nonarithmetic class, such as a "Document" class, shouldn't overload the arithmetic operators, because that imparts a new semantic to those operators. This example also illustrates one of the problem-solving techniques I use for defining overloaded operators. If the meaning of an operator function is clear, the function is usually easy to write. However, if you're struggling with what a particular operator function should do, you probably shouldn't write it at all. If you can't quickly decide what an overloaded operator should do, you can assume users of your class won't easily understand what it does, either. 

In this article, I'll subdivide the C++ operators into sets that belong together. First, I'll explain or define the operator, then I'll tell when and why to overload it, and finally I'll describe the conditions where I overload each of the operator sets. For each section, I'll give a few examples of classes in either Microsoft Foundation Class Library (MFC) or the Standard C++ library that do or don't support each operator. I'll also explain why I grouped that set of operators together. I've ordered the groups from most likely to least likely to be defined. In each group, I list the proper function prototypes for each function, inserting MyClass as the generic class name. 

I/O Group: <<, >> 
This is the most common set of overloaded operators you'll write. In fact, most client programmers expect you to write these operators to support iostreams for your class. If your class supports persistence, you should expect to write these functions. I write these functions in addition to the CArchive versions supported by MFC. You should always write these functions for your classes, unless you want to explicitly disallow saving your objects to a file and later restoring them. For example, the MFC CString class supports persistence, while the MFC CDC class doesn't. CString represents a string, which should be able to save and restore itself to a file. CDC models a device context, which is an operating system resource that can't be restored later. 

These operators write the insertion and extraction operators for any class that supports persistence: 



ostream& operator << 
	(ostream& o, const MyClass& c);
istream& operator >> 
	(istream& I, MyClass& c);

Note that these two operators are global functions, not member functions. The first parameter to each function is the stream. If the two operators were member functions, they'd need to be members of the iostream classes. The iostream classes are part of the Standard C++ library. You can't make additions to the class definition, so you can't write the streaming operators as members. They must be global functions. You write these functions as friends of your class so they can access all the member variables. 

Comparison and Assignment: =, !=, ==
These operators write the assignment operator for any class you can copy by value. If you've written a copy constructor for your class, you want to write these functions. Once again, these functions are common additions to your class. It's more common to include these operators than to leave them out. 

All the comparison operators are related to assignment. You'll usually provide a copy constructor and an assignment operator in your class. However, if you support assignment, you should support the ability to compare objects for equality. It's common to write the != operator in terms of the == operator. In fact, if you've explicitly hidden the assignment operator because of memory constraints, the comparison operators are still worthwhile. 

MFC's CRect class supports all these operations. Although you can imagine what it means for two rectangles to be equal, MFC's CBrush class can't. Should the assignment create two brushes that point to the same system resource, or should it create a new system resource? Either one might make sense. Programmers that read code using a CBrush assignment statement wouldn't know how the underlying GDI resource was being managed. Client programmers would need to know which choice was made and write their code accordingly. As an analogy, think of what happens when you assign one pointer variable to another. You need to make sure the memory referred to by both pointers is freed only once: 



// as global operators:
bool operator == (const MyClass& l,
	const MyClass& r)
{
	bool isEqual;
	//... test each member, 
	// set isEqual.
	Return isEqual;
};

bool operator != (const MyClass& l, 
	const MyClass& r)
{
	return ! (l == r);
}
// As member functions:
bool operator == (const MyClass& r) 
	const
{
	bool isEqual;
	//... test each member,
	// set isEqual.
	Return isEqual;
};
bool operator != (const MyClass& r)
	const
{
	return ! (*this == r);
}

Ordering Relations: <, >, <=, >=
The Standard Template Library (STL) uses ordering relations for all its searching and sorting algorithms. You should write these functions whenever your class's objects have a natural order. For instance, none of the MFC objects that wrap Graphical Device Interface (GDI) objects supports any of these operators. However, the CString class supports all of them. 

STL uses the less-than operator whenever it makes comparisons to sort and search. And STL algorithms require only the less-than operator�none of the others. Although STL restricts its requirements to the less-than operator, don't impose that restriction on all users of your class. I prefer giving client programmers access to all forms of ordering relations. Also, if a class has defined the ordering relations, all the equality operators are defined as well. You can avoid writing code by writing these functions in terms of one another. Note how I write >= in terms of < and <= in terms of >. A common mistake is to write operator > in terms of operator <. This fails when two objects are equal: 



bool operator < (const MyClass& r) 
	const
{
	// ... test each member.
};
bool operator >= (const MyClass& r) 
	const
{
	return !(*this < r)
}
bool operator > (const MyClass& r) 
	const
{
	// ... test each member.
};
bool operator <= (const MyClass& r) 
	const
{
	return !(*this > r);
}

Increment and Decrement: ++, --
These operators increment and decrement the class object. You should overload these operators in three cases: pointer types, ordered sets, and integral types. Types that model integers should support these for the obvious mathematical meaning. 

Pointer types can be pointers, vector types, database cursors, and similar classes. The Standard C++ library supplies a few examples for this operation. All the iterators in STL support increment and decrement, where possible. Those operations move forward and backward through the collection. Add these functions in a class that wraps database access; the increment and decrement operators can then move forward and backward through the database rows. 

I've used ordered sets to cycle through a color wheel, and the increment and decrement operators to move to the next or previous color. Suppose I have a set that uses the colors of the rainbow (red, orange, yellow, green, blue, indigo, and violet). Incrementing red would set the color to orange; decrementing blue would set the color to green. 

Whenever you overload the increment and decrement operators, remember that each operator has a preincrement and postincrement version. All my comments about increment apply equally well for decrement. These two statements show the difference: 



int i=5;
int j = i++; // j == 5, i == 6.
j = ++i; // i == 7, j == 7.

Notice that the value returned is different for the preincrement and postincrement versions. The C++ language defines that the preincrement version takes no parameters, and the postincrement version takes an integer parameter when you define these operators for your own class: 



MyClass& operator++ ()
{
	// ... whatever is necessary.
	return *this;
}
MyClass operator ++ (int)
{
	// Make a copy.
	MyClass rval (*this);
	// ... whatever is necessary.
	// to increment *this.
	// Return the old value.
	return rval;
}
// decrement is similar.

In general, you should support both the preincrement and postincrement versions, but occasionally, only the preincrement version. The postincrement version requires you to make a copy of the class object. Sometimes, copying an object is too expensive for a class to support postincrement. I don't add a postincrement operator when an object uses too much memory to support a copy constructor. Class users will understand that postincrement isn't supported when copy construction isn't supported. 

Addition, Subtraction: +, -, +=, -= 
These operators should perform their usual arithmetic operations. You should overload them in two cases. The first is when writing a class that models a mathematical construct, and the second is when writing a class that models a pointer. A common mistake is to overload only some of these operators, so I grouped these together. Users of your class expect that either none or all�but never just some�of these operators will be present. 

The += and the -= version are more efficient than the binary + operator. The binary version creates a copy of your object to store the result, and therefore creates extra temporary objects when the function executes: 



MyClass operator + (const MyClass& r) 
	const
{
	MyClass rVal;
	// perform operations, storing the 
	// result in rVal.
	return rVal;
}
MyClass& operator += (const 
	MyClass& r)
{
	// perform operations, storing the 
	// result in this.
	return *this;
}

Multiplication: *, /, *=, /= Integer Multiplication: %, %=
These operators perform the usual mathematical multiplication and division. Like the addition and subtraction operators, you should overload these operators only in the case of classes that model arithmetic types. I separated the integer multiplication operators because these operators only make sense for types that model integer values. 

Similar to the other arithmetic operators, if you overload one in a set, you should overload all of them. The prototypes for these functions are exactly the same as the addition and subtraction functions: for addition, simply replace '+' with '*', or '/'. The same efficiency rules apply here as well. Therefore, you should overload all variants when you overload any. 

Memory Management Group: new, delete
The C++ new and delete operators are called whenever users request a new object or release an existing object from global memory. You can write class-specific versions of these functions, or global versions. Use the class-specific versions only when objects of that class, or derived from that class, are created. The global versions are called for all memory allocations. 

The only reason to overload these functions is to improve your application's performance. If you overload these functions, you must provide the same interface, the same external behavior, as the standard functions. Having said this, it's rare to overload the global forms of new and delete. Doing that has serious consequences because it makes your library incompatible with libraries already linked with the standard form of new and delete. Also, it makes your code incompatible with any library that might have made the same decision. For example, MFC uses global new and delete operators to detect memory leaks. 

I created my own class-specific versions of new and delete after I ran the profiler on one of my apps to determine that memory allocations and deallocations were the bottleneck. In general, these are small objects created and deleted many times during the course of a program, such as a simple free-hand drawing tool. Each mouse move adds a new point to a list of points in the drawing, and each point contains two integers. Whenever the user draws a new figure, hundreds of points might be added. If the user deletes a figure, hundreds of points might be deleted. 

You can call new and delete in many ways. Whenever you overload new and delete, make sure you overload all the forms. First, overload the normal form of new and delete, called whenever someone creates a new object of that specific class type. Second, overload the array form version of new: operator new []. If you overload both forms, you get your improved version of new and delete only when clients request one object, not when they request arrays of objects. You should write a delete for each form of new that you write. 

Be aware that new and delete are inherited, even though they're static functions. This means your class-specific new and delete are called for classes derived from your class. Chances are, your class-specific new and delete functions are based on the size of the object, and your special functions aren't prepared to allocate memory for larger derived functions. You need to handle that case, usually by calling the global new operator: 



class MyClass 
{
public:
	// Two forms of operator new:
	static void* operator new(size_t 
		size); // Regular new
	static void* operator new 
		[](size_t size); // array new
	// Similar forms of operator 
	// delete:
	static void operator delete (void* 
		rawMemory, size_t size);
	static void operator 
		delete[](void* 
		rawMemory, size_t size);
}

You need to fully understand all the internal behavior of the standard versions of new and delete before you overload them (see Resources). Remember that if you write new or delete, you must write both. Also, new and delete come in many different forms. Make sure you write all that are pertinent to your particular problem. 

Pointer Dereferencing: ->, *
Use these operators with pointer types to access the memory locations they refer to. For instance, if p is a pointer to an integer, *p is the value of that integer. If pRect is a pointer to a CRect object, pRect->left is the left coordinate of that rectangle. 

You should write these operators only if the class you're writing models a pointer. They're defined for standard library auto_ptr classes and for all the STL iterators. The same rules apply when you write your own versions of these functions. I've written two versions: one for const objects, and one for mutable objects. If you don't write both versions, you'll have a hard time using your new classes in a const-correct fashion. You need the non-const (or mutable) version so client programmers can use your smart pointer to modify the object pointed to, and you need the const version to use a const object of your class type. If your class doesn't have a const dereference operator, you can't use the const smart pointer to access the object it points to: 



class MyClass
{
public:
	_Ty* operator -> (); 
	const _Ty* operator->() const;
	_Ty& operator* ();
	const _Ty& operator*()const;
};

Function call ()
Use the function call operator to treat your class type as a function. A class that supports the function call operator is called a function object. You write an overloaded function call operator in two cases. Formerly, programmers used this call to provide two or more dimensions in array classes: 



class TwoDArray {
public:
	float operator () (int x, int y) 
		const; 
	float& operator () (int x, int y);

};

But now it's far more common to write this function when you're writing a function object to use with the STL's algorithms. (I can't completely cover function objects in this article; see Resources for more information.) For example, the sort function uses the function object CompareObjects to compare objects of type MyClass: 



class CompareObjects {
public:
	// Function call operator:
	bool operator () (
		const MyClass& l, 
		const MyClass& r) const
	{
		bool rVal = false;
		// various tests.
		return rVal;
	};
};
// usage:
extern vector < MyClass > array;
sort (array.begin (), array.end (), 
	CompareObjects ());

Notice in the two examples that you're free to define the number and type of parameters for the function call operator any way you want. 

Array Access: []
Use this subscripting operator to access individual elements in an array. You should define this operator only in classes that model a single-dimension array. Be aware of two points when you overload this operator. First, the subscript operator is a binary operator, which means that only one parameter is defined for this operator. You can't use this operator for multidimensional arrays. Second, you can use any datatype to index the array. This allows you to create any type of associative array. The next example shows the syntax for a string dictionary class. You put a string inside the brackets to access the definition: 



class MyDictionary {
public:
	// Array operator:
	string operator [] (const string& 
		word) const
	{
		string definition =
			"who knows";
		// find definiton.
		return rVal;
	};
	// To change a definition:
	string& operator [] (const string& 
		word);
};
// usage:
extern MyDictionary Websters;
string def = Websters["alligator"];

Bitwise Operators: ^, &, |, ~, ^=, &=, |= 
Use these operators to manipulate the individual bits inside integral values. ^ is the EXCLUSIVE OR operator; & is the bitwise AND operator; | is the bitwise OR operator; and ~ is the bitwise NOT operator. You use these with integers for bitmask manipulation. 

I've never run into a practical use for overriding the bitwise operators. They're only defined for integral types. I haven't found a reason to add new classes that model an integral type. 

Not used: !, <<=, >>=, &&, ||
! is the logical NOT operator. It negates the expression to its right. <<== and >>== are the bitwise shift-with-assignment operators. They perform a left or right shift on an object and assign the result. Use the comma operator to create a compound statement. The && is the logical AND operator, and the || is the logical OR operator. 

I've seen the ! operator sometimes used for testing validity, but I don't recommend it. The idea is that if !object is true, then the object is in an invalid state. That is the only use I've seen for this operator. The >>= and <<= aren't used because they would mean the bitwise operators, rather than the more normal streaming operators. Unless your class models integral values, bitwise shifts don't make sense. 

The logical AND (&&) and logical OR (||) aren't overloaded because they would conflict with the normal short circuits in conditional expressions. The comma operator isn't overloaded because no one expects it to be. For more information, see Resources. 

Overloading operators is a helpful technique, but you need to apply it correctly to get the most out of it. You also need to make sure when client programmers use the overloaded operators, they write clear and concise code. Always ask yourself if writing the operator vs. writing a regular function more clearly describes your intent. 


Bill Wagner is the president/software architect for Midwest Seas Software Development Inc. Bill has several years of experience in Windows and C++ programming and specializes in C++, Java, and COM-based enterprise-programming solutions. Reach him at wwagner@midwestseas.com, or through www.midwestseas.com


c0Title: ATL and Upside-Down Inheritance
c1Code:
Understanding ATL's atypical design approach
http://www.devx.com/premier/mgznarch/vcdj/1999/julmag99/atlinherit1.asp 

By Jim Beveridge 
System Notes 
To replicate the steps described in this article, you will need: 
Visual C++ 6.0 
 
Outside the ivory towers of object-oriented design theory, objects or interfaces are not always independent and cannot always be expressed cleanly using traditional class design. For example, it can be quite difficult to build a class based on multiple objects or interfaces that interact with each other. Because of the interdependency between ActiveX interfaces, the designers of the Active Template Library (ATL) were forced to use an unconventional approach to cleanly express the relationships as C++ objects. In this issue we will try to design our own classes to understand the design approach and implementation of ATL. 

There are three driving principles behind ATL: small size, fast execution, and flexible architecture. Creating a flexible architecture is not a simple task. It is commonly assumed that flexibility and small code size are mutually exclusive concepts. 

 
MFC  

If you have programmed in the Microsoft Foundation Classes (MFC), you know that these principles are, in many ways, the opposite of MFC. The driving principle behind MFC is simplicity, which means minimizing usage of advanced C++ constructs and keeping the class count low. Let's look at MFC's structure and contrast it with ATL's structure. For example, take the case of an MFC CWnd. A CWnd inherits from CCmdTarget. Here is a breakdown of the functionality provided by these classes: 

CWnd Windows HWND wrapper
ActiveX control wrapper  
CCmdTarget Message map and WndProc handling
Automation handler 

These classes are overloaded-they contain much more than a single piece of functionality. This leads to code bloat. If you want to use only the wrappers for HWNDs, like the member functions CWnd::InvalidateRect() and CWnd::IsWindowVisible(), you must accept all of the baggage in CWnd as well as all of the baggage of CWnd's base classes. In MFC, this adds up to over a megabyte of code just so you can have two handy wrapper functions that compile into a few bytes each. 

Let's pretend we are designing MFC from scratch and want to create an architecture that meets the goals of small size, fast execution, and flexible architecture. 

 
Design #1: single inheritance  

We'll start with the Window structure and build out from there. Window should be very lightweight. We'll put the HWND into it, add the various wrapper functions to hide ::SendMessage(), and put everything else in other classes. 

As a litmus test, we'll use the is-a and has-a design criteria for inheritance versus aggregation. A window has-a message map. An ActiveX control wrapper is-a window. AutomationHandler could probably go either way, but I'll choose inheritance, so a Window is-an AutomationHandler. 



Now that we have a reasonable approach, let's see how this fits into our plan of small, fast and flexible. I'll rank them on a scale of 1 to 5, with 1 being "poor" and 5 being "excellent." 

Small: We can now use a Window without the overhead of an ActiveX control, but we still get saddled with a MessageMap and an AutomationHandler. Rating: 2 
Fast: To allow the user to customize the classes, there will be numerous virtual functions and very few inline functions. Rating: 3 
Flexible: Because Window derives from AutomationHandler, the only way to adjust AutomationHandler's behavior is to hope that functions you want to override are made virtual. In addition, there is no way to modify the functionality of MessageMap with a derived class because it is a hardcoded member of Window. Rating: 2 
This is not a viable solution. 

 
Design #2: mixin interfaces  

For our second try, let's consider the idea of "mixin interfaces." (For more on mixin interfaces, see my column in the August/September 1998 issue of Visual C++ Developers Journal, available online at www.vcdj.com/magazine/augmag98/mixin1.asp.) With this arrangement, the Window is the basic building block, and we have the option to derive it from Automation, MessageMap, and ActiveX Control handling (AxControl). Interface classes are denoted by prepending a capital I. 



The problem with using strict mixin interfaces is that a mixin interface is abstract and contains no implementation. We clearly would not want to have to implement everything ourselves in Window, so this solution does not work. 

We are, however, starting to edge ourselves in the direction of ATL. ATL makes extensive use of multiple inheritance. Many of the base classes for ATL objects are COM interfaces, which are themselves abstract base classes. 

 
Design #3: modified mixin interfaces  


The problem in Design #2 is easy to fix. We can add a layer of implementation between Window and the base classes that make up the interfaces. The implementation classes are denoted by adding Impl to the end. 



This design seems substantially better than Design #1. Interfaces are factored out so objects like Window can be passed around according to the interfaces they implement. The implementation is separated from the definition, so a new UserAutomationHander can be created using the same interface as AutomationHandlerImpl. 

However, despite the improved design, we have made only minimal progress in the direction of ATL's goals: 

Small: We are back to MFC size, because nothing is optional. A developer cannot use the Window object without bringing in everything else. Rating: 1 
Flexible: Window is still hardcoded to derive from the various implementation classes, so it would not be possible for the user to add a special version of the Automation Handler. Rating: 3 
Our design goals are looking increasingly difficult to achieve. 

 
Design #4: user-defined foundation  


Our primary problem until now has been making the Window object the most derived class. So long as Window inherits from the other classes, the base classes will be hardcoded, which means that it will not be possible to pick and choose them. The solution is to make Window a base class too and force the user to define the most derived object. 



Let's see how this version scores. 

Small: The user can choose which interfaces to include and can eliminate any that aren't needed. The interfaces are completely factored, so the baggage is minimized. Rating: 5 
Flexible: Because the user specifies all of the inheritance information, it is easy to add classes to override default functionality in any interface. However, the requirement for virtual functions within the interfaces still remains. Rating: 4 
There is only one problem with this class hierarchy: it doesn't work. There is no way for any of the interfaces to call any of the other interfaces. 

 
Getting a window handle  


For the above class design to work, the base classes must be able to freely call functions in other base classes. For example, what if AxControlImpl needs the window handle stored within Window? This is a painful problem to solve in C++. There are several solutions that seem promising, but there are various problems associated with each: 

Access the member variable directly, such as this->m_hWnd, or call a member function, such as this->GetHwnd(). 
Although the object is really a UsersWindow that contains a Window, AxControlImpl does not "know" this, and therefore cannot access the Window portion of the class with a pointer to an AxControlImpl. The same problem exists when a base class cannot access a member variable in a derived class. 

Call a member function that is common to both classes with the same name in each. 
In C++, sharing a common name doesn't mean anything unless there is a direct base class/derived class relationship. In this case, the two classes are siblings, so they cannot directly call member functions in each other. 

Create common member functions by using a common base class. 
This solution is deceptive. You want to end up with a diamond pattern inheritance tree so that the two siblings share a common parent. However, if you derive both siblings from the same class, you end up with two instances of the base class, not a common parent. For example, if Window and AxControlImpl derive from class WindowHandle, you would end up with this inheritance tree: 



Force a common base class using a virtual base class. 
If we derive Window and AxControlImpl from WindowHandle, we could declare WindowHandle to be a virtual base class. This declaration creates the diamond-shaped inheritance tree we desire. The problem is that we would be back to hardcoding a common base class, and it would be impossible for another developer to extend the solution by adding new functions to the virtual base class. Also, the compiler has to jump through hoops to implement virtual base classes, so we could suffer an appreciable performance hit. This solution loses points on speed and flexibility. 

Use run-time casts. 
Run-time casts come closest to a working solution. The statement dynamic_cast<>() has the capability to safely cast a pointer to a sibling. For example: 

Figure  
void AxControlImpl::SomeFunc()
{
	Window* pWnd = dynamic_cast<Window*>(this);
	if (pWnd)
		HWND hWnd = pWnd->GetHwnd();
}

 


This solution is viable but not perfect. It loses points on speed because the use of virtual functions prevents the compiler's optimizer from making the fastest, tightest code. In addition, dynamic_cast<>() will have to traverse the hierarchy every time it is called. The dynamic_cast<>() statement does its hard work at run-time, not compile time. 

Use a helper function. 
The most simple solution would be to have different virtual helper functions in Window and AxControlImpl, then tie them together in UserWindow. However, while flexible, this would increase the development burden because users of these classes would always have to manually implement the helper function instead of simply inheriting the necessary functionality. 

 
The ATL solution  


Until I looked at ATL, I would have said that the problem we're discussing is unsolvable and that we'd have to accept some compromises. However, ATL is able to successfully implement Design #4 by using some advanced C++ constructs. 

ATL solves three problems: 

Virtual functions and virtual base classes cause a performance hit and should be avoided if possible. 
Base classes must be able to communicate with each other without help from the derived class that the user implements. 
Users must be able to modify the hierarchy above them. MFC users are familiar with the problem that there is a CScrollView and a CFormView, but no easy way to create a CScrollFormView. 
ATL's solution is to use templates to access sibling classes in the hierarchy and to define base classes. 

 
Accessing sibling classes  


ATL accesses sibling classes by casting the this pointer to a pointer to the most derived class. This information is provided as a template argument, so the ATL implementation is not hard-coded to a particular derived class. 

Here is an example of the technique, expressed in terms of the example we have used so far: 

template <class T>
class AxControlImpl
{
public:
  void Update();
  {
    T* pT =  
	  static_cast<T*>(this);
    pT->UpdateWindow();
  }
};

 


Note that the implementation uses a static_cast<> instead of a dynamic_cast<>. The calculations for a static_cast<> are performed at compile time, so there will be no performance hit at run time. In addition, this code doesn't care where UpdateWindow() is implemented. If the derived class inherited from Window, then the version in Window will be used, but the implementation in AxControlImpl is not hardcoded to depend on the existence of Window. 

This class template for AxControlImpl is instantiated by code like this: 

class UserWindow : public 
		AxControlImpl<UserWindow>, Window
{
};

 


The derived class passes its type as the template parameter to AxControlImpl. When the template is instantiated, the pointer pT in AxControlImpl::Update() becomes a pointer to UserWindow. 

Now look at the definition of UpdateWindow() in Window: 

class Window
{
public:
    HWND m_hWnd;

    BOOL UpdateWindow()
    {
        return ::UpdateWindow(m_hWnd);
    }
};

 


Note that UpdateWindow() is inline but not virtual! Because it isn't virtual, the compiler can uniquely determine which function will be called at compile time and use early binding instead of late binding. Because the function is inline, the optimizer can do its job and optimize away the member function call and the cast. The generated code will contain nothing but a call to the SDK function ::UpdateWindow(). 

This ends up being a weird form of compile-time polymorphism. Although the function is not virtual, the compiler will resolve duplicates in the hierarchy by calling the most-derived definition. This is the behavior we would normally get at run-time with the use of virtual functions. In this case, what is being resolved is the object structure that the user defined, which will be fixed once the program is compiled. Virtual functions would add unnecessary overhead. 

 
Base classes with templates  


If you've been waiting to learn what I mean by "upside-down inheritance," then wait no longer. Traditionally, when you derive from a class, everything above your immediate base class is fixed. This was the key design problem we encountered in Designs #1, 2, and 3 because we lost flexibility every time we introduced a base class. 

ATL solves this problem by allowing the developer to use template arguments to specify the base class of a base class. The classes I used as examples in Design #4 are quite similar to the classes in ATL. Here is what an ATL definition would look like (the list of base classes to CMyControl has been heavily edited). 

class CMyControl : 
	public CComObjectRootE< 
		CComSingleThreadModel >,
	public CComControl< CMyControl, 
		CWindowImpl< CMyControl, CWindow > >
{
};

 


The first template parameter to CComControl is the most derived class so CComControl can access siblings in the hierarchy. This works just as it did for AxControlImpl in the last section. 

The second template argument is the definition of what CComControl should use for a base class. This allows you to insert your own classes into the class hierarchy, thus making ATL extremely flexible if you need to change its behavior. If you browse your own ATL project, you may not see this template argument, because ATL automatically uses the default if it isn't specified. 

For example, this list shows the derivation hierarchy of CMyControl, with the base class at the top and the most derived class at the bottom: 

CWindow
CWindowImplRoot<CWindow>
CWindowImplBaseT<CWindow>
CWindowImpl<CMyControl, CWindow>
CComControl<CMyControl, 	
		CWindowImpl<CMyControl, CWindow> >
CMyControl

 


The two classes in blue are both defined by the template arguments to CComControl and can therefore be replaced or overridden by the developer. For example, you could subclass CWindow and create CCenteredWindow. You would then change the template argument to CWindowImpl, and your new class would be inserted into the hierarchy. 

Remember that most functions are not virtual. If you use CCenteredWindow to override functions in CWindow, then your override will be called, not because it is virtual, but because it is the most derived implementation of the function. 

The reason I call this upside-down inheritance is that the most derived class defines the base class and therefore defines the behavior of the base class. This is the opposite of the typical case, where the derived classes have little or no control over the behavior of the base class. 

 
Summary  


Let's look at the ratings of ATL's implementation: 

Small: ATL is highly factored and most interfaces are optional. It has very little "baggage." Rating: 5 
Fast: ATL avoids virtual functions, and therefore allows the compiler to aggressively optimize the code, often removing both the virtual indirection and the function call itself. Rating: 5 
Flexible: The ability to redefine an existing class hierarchy is quite unusual. It offers a much higher degree of flexibility than the other approaches examined in this article. Users are, however, tied to the dependencies between the sibling classes. These dependencies can be very frustrating if you want to use an interface that unnecessarily relies on an interface you do not have or want. Rating: 4 
The big thing you give up to make all of this work is simplicity. It is easy to get a solid feel for MFC's class hierarchy, even if the internal implementation can be cryptic. However, the class hierarchy for ATL is complex and requires significant effort to get the most out of it. This article describes a justification and the implementation behind the ATL class hierarchy and should provide a solid basis for improving your understanding. 

 
Jim Beveridge is an independent consultant specializing in software architecture, design, and project management. He is the author of Multithreading Applications in Win32 from Addison-Wesley and a frequent speaker at the Visual C++ Developers Conferences. Reach him at jbeveridge@fawcette.com


c0Title: ATL Windows Traits
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/04apr00/ap0400/ap0400.asp
by Davide Marcato 
     Q.Understand Windows Traits 
I'm an Active Template Library (ATL) COM programmer who focuses on enterprise-application middle-tier development primarily. I keep hearing fellow programmers use the expression "ATL windows traits," but I don't know what it's all about. As a COM programmer, should I know about this? 


A.Programmers first used ATL as a C++ framework to simplify writing COM code, especially COM components. Microsoft invested in ATL and turned it into a full-fledged set of templates; programmers no longer needed to implement boilerplate coclass functionality repeatedly, but retained the performance and low footprint they sought. 

Today, ATL 3.0 still operates as a COM programming framework. However, it also offers a way to perform general user interface Windows programming in C++. Microsoft's goal was to create a mid-level alternative between the C-oriented Win32 SDK and the C++- and macro-oriented MFC�an environment more comfortable than C but less convoluted than C++. If you're not a UI developer, you might not know about this part of the framework. It has nothing to do with COM, and only involves windows, messages, and dialog controls. Needless to say, windows traits fall in this category. 

Most GUI programmers know that all windows have a defined set of styles, identified by self-explanatory constants such as WS_CHILD and WS_DISABLED, and another set of extended styles such as WS_EX_TOPMOST. Win32 has its own set of defined styles. It often makes sense to associate definite groups of styles and extended styles. For example, frame windows have different styles from child windows. When you create a Window class, you know how it's going to be used. You know beforehand that all dialog box controls have the WS_CHILD style set, whereas top-level windows have the WS_OVERLAPPEDWINDOW button on. 

The Windows USER(32) module supports window templates through the Window classes, of which every window must be an instance. Yet, you can't immediately set the default styles for a Window class with the Win32 APIs. Instead, you have to manually specify the styles and extended styles as input parameters to ::CreateWindowEx() or one of its wrappers. 

To fill this small commodity hole, ATL's creators faked an additional thin layer between the client creation code and the Window class to permit default styles to associate with the Window class. This thin layer comes as a class template, called windows trait (CWinTraits). This code snippet shows the source code from the ATL 3.0 source file Atlwin.h: 



/////////////////////////////////////////
//////////////////////////////////// 
// CWinTraits - Defines various default values 
//   for a window
template <DWORD t_dwStyle = 0, DWORD 
   t_dwExStyle = 0>
class CWinTraits
{
public:
   static DWORD GetWndStyle(DWORD 
   dwStyle)
   {
      return dwStyle == 0 ? t_dwStyle : 
         dwStyle;
   }
   static DWORD GetWndExStyle(DWORD 
      dwExStyle)
   {
      return dwExStyle == 0 ? t_dwExStyle : 
         dwExStyle;
   }
};

The two DWORD template parameters holding the default styles and extended styles represent the class's only state, while two self-explaining accessor methods make up the public interface. Using CWinTraits with the ATL windowing classes, most notably CWindowImpl<>, is simple: 



typedef CWinTraits<WS_CHILD, WS_EX_CLIENTEDGE> CChildWindowTraits;

class CChildWindow : public
         CWindowImpl<CChildWindow, 
            CWindow, CChildWindowTraits> 
{
   // Derived window class 
   //   implementation�
};

A correlated ATL class template, CWinTraitsOR<>, allows you to add styles to an existing Window traits class of reference: 



template <DWORD t_dwStyle = 0, DWORD 
   t_dwExStyle = 0, class TWinTraits = 
      CControlWinTraits>
class CWinTraitsOR
{
public:
   static DWORD GetWndStyle(DWORD 
      dwStyle)
   {
return dwStyle | t_dwStyle | 
   TWinTraits::GetWndStyle(dwStyle);
   }
   static DWORD GetWndExStyle(DWORD 
      dwExStyle)
   {
return dwExStyle | t_dwExStyle | 
   TWinTraits::GetWndExStyle(dwExStyle);
   }
};

ATL programmers have also predefined a few common windows traits: 



typedef CWinTraits<WS_CHILD | WS_VISIBLE | 
   WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> 
      CControlWinTraits;

typedef CWinTraits<WS_OVERLAPPEDWINDOW 
   | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 
      WS_EX_APPWINDOW | 
         WS_EX_WINDOWEDGE>
   CFrameWinTraits;

typedef CWinTraits<WS_OVERLAPPEDWINDOW 
   | WS_CHILD | WS_VISIBLE | 
      WS_CLIPCHILDREN | 
         WS_CLIPSIBLINGS, 
            WS_EX_MDICHILD>
                CMDIChildWinTraits; 

typedef CWinTraits<0, 0> CNullTraits;

Window styles are a fundamental Windows feature, but setting the styles time after time can be tedious, and it leaves room for errors. If you program with ATL and encounter these problems, windows traits are handy. They enable you to set or access window styles as atomic groups identified by a distinct class name. The magic of template specialization makes this possible�without compromising performance or imposing awkward syntax. 


Davide Marcato is president and founder of Marcato Consulting (www.marcatocons.com), a software development and consulting firm specializing in Windows DNA and Internet enterprise solutions. Davide writes for many magazines, including Visual C++ Developers Journal, Dr. Dobb's Journal, MIND, and COM Developer. Contact him at www.DavideMarcato.com
 


c0Title: Better Debug Output
c1Code:
You might know you can use OutputDebugString() or one of the trace macros (ATLTRACE, TRACE, and so on) to print messages to the VC++ IDE debug window. I've recently found that formatting your message's header (first line) in a style used by VC++ compiler messages gets you the same interactive behavior as you get with VC++ compiler/runtime messages. Double-clicking on a line brings up the source file with the correct line selected; the text of the message is displayed in blue in the status bar. The required format is: 

<Full-Path-to-Source-File>(<line#>) : <Text of the message>
Like many other C++ developers, you might already print this information using __FILE__ and __LINE__ system macros. All you need to do is change the parameter order. If not, here's an example, using the ATLTRACE macro: 
#define MYTRACE(szMsg) ATLTRACE("%s(%d) : %s", __FILE__, __LINE__, (szMsg))
Try it by putting this line in one of your ATL project's CPP files, building the project (make sure it's a debug build), and running it from the IDE: 
MYTRACE("Double-click me to see the source file!");
This will result in output like this in the IDE's Debug window when the MYTRACE() line is hit: 

C:\MyProj\MyComponent.cpp(188) : Double-click me to see the source file!
�Leonid Khotomliansky


c0Title: Bugs, Bytes, and Datatypes
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/03mar00/qa0300/qa0300.asp
by Danny Kalev 


     Q.Nix Macros 
We're using many long macros in a project. How can we debug them (setting breakpoints, and so on)? Is there a solution for debugging macros in Visual C++ 6.0? 
What you need:
Visual C++ 6.0 Service Pack 3
Win32
Windows NT4 Service  
 
A.Unfortunately, you can't debug macros for a simple reason: As far as the compiler is concerned, they don't exist. The preprocessor expands all macros in the source file before the compiler scans it. Therefore, the compiler doesn't generate the necessary debug information for the debugger. For this reason�as well as many others�macros are anathema to good programming. You should avoid using them in the first place. 

Visual C++ happens to support macro debugging to a certain extent. It can show you the declaration of the macro, but that's about it. It won't step into a macro's source lines and it won't let you assign new values to macro symbols. 

Your "many long macros" sound suspicious to me. I suggest using inline functions instead. 

Q.Set a Breakpoint in a Constructor 
I can't create an instance of the derived class using operator new. The base and derived classes differ only by a virtual function. The error messages I receive at run time ask me to specify the path for files such as: 



new.asm, strncpy.asm

A.Although you don't mention which compiler you're using, it sounds like you're attempting to step into the implementation code of operator new using the Visual C++ debugger. Normally, you don't need to do that. Simply use the "step over" command to exit from the implementation code. Instead of using the "step into" command, set a breakpoint in the constructor of the class whose instance you're attempting to create. 

You should note that many time-critical, low-level functions, such as memcpy, strncpy, and memset, are written in assembly. When the compiler sees a call of such a function, it inserts its assembly code inline (rather than actually calling a function). When you try to step into the called function, the debugger needs to know where these functions' assembly source files are located. You can find these files in the Visual C++ in-stallation CD (just run a search to locate these files, then direct the debugger to look for them on the CD). 

Q. Create Cross-Platform C++ Code 
I'm looking at Visual Studio 6 as a development platform. (It contains Visual C++, Vis-ual J++ , and Visual Basic.) Can I use this development platform to create executables for both NT and AIX Unix? If so, are there any "gotchas"? I've heard that C++ contains extensions that can't be used with Unix, and I understand that the final executable must be compiled on the target system. 

A.You can use Visual Studio to create cross-platform C++ code. Make sure you use only standard features and avoid any Microsoft- or Windows-specific extensions. In particular, avoid DLLs, MFC, ATL, WinAPI, and COM. In other words, create your project as a statically linked console application. 

Note also that Visual C++ is a bit behind the standard, so it might not support some important C++ features that were added to standard C++ relatively recently, including partial template specialization and exception specification. However, it produces efficient code on the Windows platform. Make sure your AIX C++ compiler is as ANSI/ISO-compliant as possible. 

Q.The Operator << is Ambiguous 
My small program (see Listing 1) compiles and runs correctly on one machine and generates this error on another: 



'operator <<' is ambiguous

Both computers are running Windows NT4 Service Pack 4, Microsoft Visual Studio C++ 6.0. And the Visual C++ Studio tab settings for the Tools | Options | Directories Tab and Tools | Options | Help System Tab are the same on both computers. Can you please tell me where the source of this problem lies? 

A.Your code is fine. The first release of VC++ 6.0 had several bugs with handling friend functions. These bugs were fixed in the VC++ Service Packs that came later. I recommend installing the latest VC++ 6.0 Service Pack on the machine where the compilation errors occur. This should solve the problem. 

Q.The Truth Behind _CrtDumpMemoryLeaks( ) 
I've written this small program in Visual C++, and it seems that STL is leaking memory: 



#include <iostream>
#include <crtdbg.h>

using namespace std ;

void main()
{
  _CrtDumpMemoryLeaks( );
}

The output is a memory dump of 33 bytes and 40 bytes. How can this be? 


A.This is because _CrtDumpMemoryLeaks( ) lies. The iostream objects are constructed before main() starts and they are destructed after main() exits. Therefore, _CrtDumpMemory-Leaks() thinks there's a memory leak because the memory isn't released before main() exits. Instead, the memory is released at a later stage, during the destruction of the iostream objects. 

Q.Templates and Nested Classes 
What is the C++ syntax for defining a function that belongs to a nested class contained within a template class? For example: 



template <class Type>
class A
{
  protected:
  // nested class
  class B
  {
    void BFunc(Type BFuncVar);
    // other stuff for class B
  };

  // other stuff for class A
};

If BFunc is implemented inside the class definition, everything works. But I want to define BFunc outside the class definition, and can't figure out what the syntax should be. I tried something like: 



template <class Type>
void A::B::BFunc(Type BFuncVar)
{ ... }

and the linker complained that it couldn't find the function. (I was using Visual C++ version 6.) 

A.Unfortunately, Visual C++ 6.0 has a bug that causes a link error when you define member functions of a nested class template outside their class definition. The compiler doesn't generate code for such member functions unless they're implemented inside their class (see Links). 

That said, you still need to make some corrections to make your code syntactically correct. You can then use a different compiler such as C++ Builder 4.0, which supports out-of-class member functions of a nested class template, or use an explicit specialization as a workaround (see Links). 

Here are the necessary corrections. First, create an instance of the nested class inside the containing template. Otherwise, the inner class is useless. Second, the nested class's member function is implicitly declared private. Change its access to public. Remember that you can't call a nonpublic member function of a nested class from its containing class. Finally, in the out-of-class definition of BFunc, you must specify the template parameter after the class name A. 

Here's a complete example: 



template <class Type>
class A
{
  protected:
  // nested class
  class B
  {
  public: // !!add an explicit access specifier
    void BFunc(Type );
    // other stuff for class B
  } b; // !!create an instance of the nested class
public:
  void f(Type t) {b.BFunc(t);} // !!use nested object
  // other stuff for class A
};

//!!definition of nested class's member
template <class Type> void 
A<Type>::B::BFunc(Type t) // note: A<Type>::
{
 t = 0;
}
int main()
{
 A <int> aa; A<char> ab;
 aa.f(5); // fine
 ab.f('c'); // fine
}

Q.Eight-Byte Integers? 
I'm looking for a C++ integer datatype that takes eight bytes. I've tried long, long int, and so forth, but they're all four bytes on Windows NT. I need an eight-byte integer datatype for an encryption algorithm. Can you tell me what to do? 

A.Standard C++ doesn't define an eight-byte integer type. However, this situation will change soon, because C9X (the new C draft standard) now defines the long long datatype, which is a 64-bit integer on most platforms. 

In practice, many C++ compilers already define a nonstandard integer type that holds eight bytes. Visual C++, for instance, defines __int64 and __uint64 for signed and unsigned eight-byte integers, respectively. You can use these types on Windows NT. 

Q.Template Troubles 
I'd like some help on template specialization. Consider these two declarations: 



template <class T> void func(T s);
template <class T> void func(T *s);
/*..their implementations go here*/
main() 
{
  int i=32;
  int *j=&i;
  func(i);
  func(j);
}

Which function is going to be called, and when? The code example is from Bjarne Stroustrup's book (see Resources). I tried it in the Visual C++ 6.0 compiler, but it cribbed an ambiguous call in the call func(j). I have doubts regarding the call func(j) because with it, the first template would be called. Stroustrup writes that when there is more than one template-based candidate, the more specialized one wins. He goes on to say that the first template function, template <class T> void func(T s); , would be called. As I understand, template <class T> void func(T *s) is more specialized�it's customized for pointers and 'j' is a pointer in our sample program. 

A.Unfortunately, Visual C++ 6.0 doesn't support partial template specializations yet. So this example, albeit legal, doesn't compile. 


Danny Kalev, a system analyst and software engineer, specializes in C++, and object-oriented analysis and design. He's a member of the ANSI C++ standardization committee and the author of ANSI/ISO C++ Professional Programmer's Handbook (Que, 1999, ISBN: 0789720221); check out a review at www.devx.com/free/books/bookreview.asp?bookid=286. 
 


c0Title: Build Versatile 3-D Apps
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/07jul00/mf0007/mf0007.asp

Use Direct3D to create a robust and flexible 3-D framework that ensures correct operation on all graphics accelerators. 

by Max Fomitchev 


   Developing 3-D applications that rely on Direct3D presents a number of challenges�tedious initialization, unknown hardware capabilities, and fickle drivers, to name a few. So, you want to have a versatile 3-D framework that handles common operations and ensures correct execution of an application on different hardware configurations and in different graphics modes. Such a framework must also be robust and flexible enough to allow customization. 
What you need:
Visual C++ 6.0 SP3 
Windows 95, 98, or 2000 
DirectX SDK 7.0 or later  
 

In this article, I'll discuss an MFC framework that provides flexible control over Direct3D and ensures correct operation on all graphics accelerators in full-screen or windowed mode. This framework combines features of many DirectX SDK samples as well as invaluable results of experimentation. The framework supports dynamic device, driver, and mode selection; correctly handles Windows desktop-incompatible drivers such as 3dfx Interactive's Voodoo; allows the opening of GUI windows in full-screen exclusive mode; and displays an alternative mouse pointer whenever the standard one is not available. Finally, the framework ties Retained and Immediate Mode objects together, providing versatile control over rendering. 

When I started working on a new game, I chose Direct3D Retained Mode (D3DRM). It's a higher-level API than Direct3D Immediate Mode (D3DIM), so it allows rapid 3-D application development. But I didn't want to limit myself to D3DRM only because I suspected that the game might suffer from rendering performance bottlenecks. Plus, I had a number of other 3-D applications such as the 2-D Surface Deformation Demo (see Links), that worked fine on most cards, but were glitching�failing to select the Direct3D Hardware Abstraction Layer (HAL)�on others. I also wanted the application to display dialog windows, which presented a slight problem in full-screen exclusive mode. Clearly, the mess needed order, and I needed a framework to use as a starting point or as a template for developing a new 3-D application. 

Framework Requirements
I eventually came up with this list of requirements for the new 3-D framework. The framework needed to: 

Ensure correct application operation on all 3-D accelerators. 
Support full-screen/windowed mode switching and device/driver/graphics mode selection at run time. 
Support GUI windows in full-screen exclusive mode. 
Support both D3DRM and D3DIM. 
The desired versatility comes at a price: I had to deal with many nuances, including window and mouse pointer management, texture preservation, graceful handling of failures, and graphics driver discrepancies. 

   
Figure 1. Don�t Let Direct3D Puzzle You! Click here.

 
Luckily, the DirectX SDK provides ample resources for building such a framework. The unfortunate (and fun) part is that all the needed functionality is scattered among the SDK source files and often requires extensive tailoring. The Direct3D framework described in this article inherits and enhances the functionality of the MFC Fog Immediate Mode and the Fly Retained Mode samples. MFC Fog shows you how to integrate D3DIM rendering into an MFC application, whereas the Fly sample provides the basics of D3DRM operation. 

The full-screen version of the Fly sample (FlyFS) seems fairly attractive except for the fact that textures are not preserved when you toggle between full-screen and windowed mode. The MFC Fog sample handles the textures correctly. 

The DirectX 6 SDK includes a CD3DFramework class (called CD3D-Framework7 in DirectX 7) defined in the D3DFrame sample. The class provides a simple interface and encapsulates all the IM initialization functions. You can find the CD3DFramework class source files d3dframe.h, d3dframe.cpp, and d3dframe.lib in the SDK \samples\multimedia\d3dim\include, \samples\multimedia\d3dim\src\d3dframe, and \samples\multimedia\d3dim\lib folders of the complete DirectX installation, respectively. These folders also contain other useful utility files for texture management and mode and driver selection (d3denum.cpp and .h; d3dtextr.cpp and .h). All the functionality is packed in the d3dframe.lib library. 

3-D Game Demo
I've implemented the enhanced Direct3D framework in a simple 3-D game: Gems 3D (see Figure 1). The application has an SDI MFC skeleton that doesn't use the Document/View model. It renders the 3-D content in the main frame window. 

By default, the application starts in windowed mode. The primary device and Direct3D HAL or RGB emulation driver are selected based on windowrendering capabilities and the driver's compatibility with the Windows desktop (such as color depth match/mismatch). 

The application allows toggling between windowed and full-screen mode, but textures are preserved, unlike the full-screen Fly sample. Also, the game doesn't crash or freeze when DirectMusic is involved (I'll discuss this in more detail later). 

You can select a different rendering device, graphics driver, or display mode using the Select New Direct3D Driver dialog (see Figure 2). The application attempts to switch to the specified mode or device and gracefully falls back when an error occurs, such as when there's not enough video memory for Z-buffer creation. 

The game can display an alternative (non-Windows managed) mouse pointer (see Figure 3). Using an alternative pointer proves especially useful when you're working with older 3-D drivers that feature annoying mouse pointer flickering (such as older ATI Rage Pro cards) or when you're using non-desktop compatible accelerators and drivers such as Voodoo. 

Finally, the game displays GUI dialogs, such as About boxes or Top Ten Score boxes, in windowed and full-screen exclusive modes. 

   
Figure 2. Choose Your Driver Click here.

 
Because of its length, the complete source code of the 3-D framework and demo application doesn't appear in its entirety in this article, but you can download it here. 

The demo workspace includes two projects: 3DFrame (the framework) and GemsDemo (the Gems 3D game demo). I've included a description of the 3-D framework source files (see Table 1). 

The 3D framework compiles into a static library (and includes files 3dframe.lib and 3dframed.lib for debugging) that must be linked with the master application. 

When integrating the framework classes with an application, you need to derive new classes from C3DScene and C3DView. In GemsDemo, for example, the CScene class is derived from C3DScene and the CGemsView class is derived from C3DView. See the downloadable source code for the full version, including class definitions. Make sure you override the necessary C3DScene methods (see Table 2). 

By adding new methods and properties necessary for supporting 3-D scene complexity and game states, you can extend the C3DScene class even further. 

Within the derived framework, the C3DView class handles almost all the Direct3D business. When using the framework, the application client window must be derived from the C3DView class. C3DView exposes these user functions: 

UserRender(HDC hDC): Overrides this function to add user elements such as overlay icons or text. 
ToggleFullscreen(): Toggles windowed and full-screen mode. 
ChangeDriver(): Opens device, driver, and display mode selection dialog. 
ToggleFramerate(): Toggles frame rate display. 
ToggleMouse(): Toggles alternative mouse pointer display. 
The application and main frame classes (CGemsApp and CMainFrame in GemsDemo) require little tailoring for integration with the framework, so it made no sense to create base classes for them. I changed the CMainFrame class only by adding the WM_MOVE and WM_ACTIVATEAPP message handlers: 



void CMainFrame::OnMove(int x,
	int y)
{
	CFrameWnd::OnMove(x, y);
	m_wndView.Move(x, y);
}
void CMainFrame::OnActivateApp(
	BOOL bActive, HTASK hTask)
{
	CFrameWnd::OnActivateApp(bActive,
		hTask);
	m_wndView.m_bActive = bActive;
}


The Direct3D framework must be notified that the rendering window's position has changed. When the application isn't active, you can save CPU by bypassing the rendering loop completely (using the m_bActive flag). 

Change the application class by calling the C3DView::InitialUpdate() member in the application InitInstance() function. Plus, overload the application's OnIdle() function to handle idle time processing for the 3-D scene rendering. 

Look Under the Hood
The C3DView class handles all Immediate Mode initialization and creates all needed IM objects, including the rendering device, view, DirectDraw buffers, and texture surfaces. The C3DView class relies on the slightly modified DirectX SDK CD3DFramework to do the job. 

For RM initialization and 3-D scene construction, the C3DView class uses its m_pScene member to represent the C3DScenebased user class. The C3DView class calls the C3DScene::Build() method for 3-D scene generation and the C3DScene::CreateDevAndView() method for RM device and view creation. 

The 3-D environment initialization starts when the InitialUpdate() C3DView class member function is called from within the application InitInstance() function. Within InitialUpdate(), the program enumerates 3-D devices with the D3DEnum_EnumerateDevices(NULL) call, and selects the primary device's HAL driver. D3DEnum_EnumerateDevices() is defined in DirectX SDK's d3denum.cpp module. The program then creates and initializes Direct3D objects by calling the Initialize3DEnvironment() member function. 

InitialUpdate() then calls Initialize3DEnvironment(),where the RM objects and the 3-D scene are created (through calls to m_pScene->Create() and m_pScene->Build()). Then the first attempt to create the IM objects is performed when the program calls Initialize3D(). If the attempt fails (perhaps because of the lack of desktop driver compatibility or inability to render in window), the application selects the software emulation driver and makes another attempt to initialize IM objects. If the second attempt fails, the application exits with an error message. Not much can be done when both the hardware and software emulation drivers fail. 

The body of the Initialize3D() member contains the calls to members of the CD3DFramework6 class, which accomplish the previous steps. The program then creates the RM device and view objects by calling m_pScene->CreateDevAndView(). 

Once the initialization is complete, the application sets the m_bReady flag and calls the rendering routine named C3DScene::Render3DEnvironment() from the application's OnIdle() handler. The rendering routine does several important things: 

It checks DirectDraw's cooperative level by calling m_Framework.GetDirectDraw()->TestCooperativeLevel() to determine whether the full-screen window has lost its focus. If the focus was lost, the application switches to windowed mode by calling GoWindowed(). 
It draws overlay text (see Figure 4), such as the game score, on top of the current rendering surface using standard GDI calls. The application obtains the rendering surface DC by calling m_Framework.GetRenderSurface()->GetDC(&hDC). 
Finally, it draws an alternative mouse pointer by overlaying an icon using the DrawIcon() GDI call. The alternative mouse pointer is selected automatically when the current Direct3D driver cannot render in the window (so determined by consulting the value of the m_bCanRenderWindowed flag). 
Whenever the users want to change the current Direct3D driver and graphics mode, the application should call the ChangeDriver() routine. The routine displays the Select New Direct3D Driver dialog (see Figure 2) and calls Change3DEnvironment() to reinitialize the Direct3D IM and RM objects 

For full-screen rendering, the Change3DEnvironment() routine creates a separate full-screen window by calling m_FullWnd.CreateEx() and by using its handle for subsequent Direct3D device and view port initialization. 

Note: You can't use the client window of the application main frame for full-screen rendering because DirectDraw doesn't allow full-screen child windows (windows with the WS_CHILD window style attribute set). 

You could also consider this alternative: Use the main frame window for full-screen exclusive mode. Using the main frame window produces several side effects, however. For one, pressing the Alt key can activate the main frame system menu. But for some applications, this might be useful. To ensure proper menu visibility, you must override the main frame's OnEnterMenuLoop() and call GetDirectDraw()->FlipToGDISurface(). The main frame border and status bar (if they exist) will be visible as well. 

   
Figure 3. A Different Point Of View Click here.

 
A negative side effect includes the loss of textures when the main frame is minimized. After the minimization, the application loses the exclusive lock on the DirectDraw primary surface and yields the control to the Windows desktop. It automatically releases the texture surfaces at that point. When the main frame window is restored, the textures are not automatically restored. With perverted textures, the 3-D scene looks funny. 

When opening a separate full-screen window, you probably want to continue handling all the commands and mouse messages the client window was handling. For this purpose, the full-screen window simply reflects its messages to its owner�the main frame client window�by redirecting the messages in the full-screen message handlers. You must manually initialize the m_pOwner pointer to the main frame. 

For convenience, the C3DView class handles WM_SIZE and WM_PAINT messages. This ensures the Direct3D view port is resized when window sizes change and ensures that "dirty" scene areas are repainted when other windows overlap the client area. 

   
Figure 4. Draw Overlay Text Click here.

 
DirectMusic Notes
Strangely enough, adding music and sound effects to the application can introduce noticeable problems for Direct3D. When DirectMusic is running, the CD3DFramework::Initialize() call fails when going to full screen or when switching to another rendering device or driver. Failure can occur in several ways: The application might lock up or you might get a general protection fault. 

After a brief investigation, I discovered that flipping to full screen conflicts with COM initialization�you must call the CoInitialize() API routine before creating the DirectMusic objects through CoCreateInstance(). To fix the problem, I've moved the CoInitialize() call to the application OnInitInstance() handler, and added the CoUninitialize() call to the application OnExitInstance() routine. 

Occasionally, a 3-D application might need to use the Windows GUI to display settings dialogs or simple message boxes. Opening Windows dialogs in full-screen exclusive mode can be tricky. When the Direct3D driver supports rendering in a window, the GUI dialog management is simple: Simply flip to a GDI surface before displaying a dialog. A slight side effect of displaying a dialog this way is that the main frame menu and title bar will be visible when the main frame window is used for full-screen rendering. 

However, the problem becomes much more complicated when using nondesktop compatible drivers such as drivers for Voodoo video cards. Flipping to the GDI surface when rendering on Voodoo results in complete loss of the 3-D scene and a switch to Windows GDI. The screen turns black, and the dialog is displayed on top of the maximized application main frame. 

To avoid this problem, you should not flip to the GDI surface, but rather blit from the GDI surface to the DirectDraw rendering surface and overlay the dialog's image on top of the 3-D scene. Obviously, you must rewrite the dialog's OnPaint() handler to accomplish this, as shown in the C3DDialog class (check the downloadable source code). Capture the dialog's bitmap by obtaining a GDI screen DC using ::GetDC(NULL) and storing it in a memory DC. 

Then call the C3DView::Render3DEnvironment() member with parameters that specify the memory DC and the bitmap dimensions for subsequent blitting on the DirectDraw back buffer. Notice that the CPaintDC object is not constructed. This forces Windows to send the WM_PAINT message to the dialog window over and over, constantly updating the screen. This effect proves useful in displaying the dialog's dynamic content such as focus and selection marks on controls and edit or combo box changes. 

Here's another helpful trick when you display a mouse pointer. In exclusive full-screen mode on Voodoo, you can't see the Windows default mouse cursor. So you should instead use the C3DView mouse icon, which is laid on top of the dialog's bitmap (see the C3DView::Render3DEnvironment() implementation). Because the screen is constantly refreshed due to the dialog's WM_PAINT message, the mouse pointer is updated as frequently as the rendering frame rate permits. 

The last modification to the dialog class: Introduce explicit window centering on screen. Normally the dialog is centered relative to the Windows desktop or application main frame. In exclusive mode on Voodoo, the desktop and application main frame coordinates don't correspond directly to the rendering screen coordinates. So the dialog might end up sitting in the corner or off screen. Add this statement to the OnInitDialog() routine to handle this inconsistency: 


GetWindowRect(rc);
MoveWindow((m_p3DView->
	m_pDeviceInfo->pCurrentMode-
	ddsd.dwWidth- rc.Width())/2,
 (m_p3DView->m_pDeviceInfo->
pCurrentMode->
ddsd.dwHeight - rc.Height())/2,	rc.Width(), rc.Height());
When DirectX 7 came out, I immediately rushed to replace my old SDK installation. Much to my surprise, my applications stopped compiling. The C3DFramework class was modified and replaced with a C3DFramework7 class that supports the IDirectDraw7, IDirect3D7, and IDirectDrawSurface7 interfaces. So I replaced all the C3DFramework references with C3DFramework7. The application compiled the next time, but still didn't work. The Direct3D RM initialization was failing when I was calling C3DScene::CreateDevAndView() from C3DView::Initialize3D(): 


...
m_Framework.GetDirect3D()->
QueryInterface(IID_IDirect3D2,
	(void**)&pD3D);
m_Framework.GetD3DDevice()->
QueryInterface(IID_IDirect3D
	Device2,
	(void**)&pDevice);
// Create RM device and view
if ( SUCCEEDED(hr = m_pScene->
	CreateDevAndView(pD3D, pDevice)) )
...
Much to my frustration, I learned that the internal architecture of DirectX 7 has changed in such way that the IDirect3D7 object doesn't inherit from IDirect3D3 or IDirect3D2. So you can't obtain an IDirect3D2 interface from an IDirect3D7 object. The bottom line: It's probably impossible to "blend" Direct3D IM and RM objects using IDirect3D7. I couldn't find a better solution other than to keep using IDirect3D3 and turn the CD3DFramework7 into a CD3DFramework6 class by replacing DirectX 7 interfaces with DirectX 6 interfaces compatible with Retained Mode. 

The enhanced Direct3D framework I've discussed provides flexible control over Direct3D; ensures correct operation on diverse hardware; and instantly enriches an application with features such as dynamic device, driver, and mode selection, alternative mouse pointer display, and full-screen mode GUI window management. All this makes the presented framework a good starting point when you develop a new 3-D application. 


Max Fomitchev is a Ph.D. candidate and an IT consultant at Systems & Programming Resources Inc. in Tulsa, Okla. He specializes in ultrasound imaging, code optimization, and 3-D graphics. You can reach Max by e-mail at maxf@webzone.net. He has a home page at http://frontpage.webzone.net/maxf/
 


c0Title: Change Bitmaps On the Fly
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/07jul00/ap0007/ap0007.asp
Supposed, Former, Entry-Point Junkie 
by Andy Harding 


   Q. Change Bitmaps On the Fly 
I have a dialog box with a bitmap in it. How can I change the bitmap while the program is running? I'm using the Windows API with C++. 

A. You can accomplish this in several ways. The easiest method is to create two bitmaps existing at the same spot on the dialog box. When the dialog starts up, hide one of the bitmaps. When you want to switch, use this code: 



ShowWindow(GetDlgItem(hDlg, 
   IDD_BITMAP1), SW_HIDE);
ShowWindow(GetDlgItem(hDlg, 
   IDD_BITMAP2), SW_SHOW);

This efficiently changes your bitmaps when you're dealing with a small number of them. But what if you want a more dynamic solution? For example, what if you need to show bitmaps that aren't in your resource file? Microsoft has provided a better way in Win32. If you create your bitmap as a static control with the SS_BITMAP attribute set, you can use the STM_SETIMAGE message to pass bitmap handles directly to the static control (see the sidebar, "How to Place a Bitmap in a Dialog Box"): 



SendMessage(hBmpWnd, STM_SETIMAGE,
      IMAGE_BITMAP,
      (LPARAM)(HBITMAP) hBmp);

Another concern is managing the various bitmap handles. I've written a simple class, called the CDynBitmap, that uses an array of HBITMAP handles and calls DeleteObject() for you (see Listing 2). It also sends the STM_SETIMAGE message to the bitmap window when the ChangeBitmap() member function gets called. The constructor is straightforward. The first argument needed is the instance handle to where the bitmap resources are located. The last item is the handle to the bitmap window: 


CDynBitmap(HINSTANCE hInst, HWND hBmpWnd);

If you're adding bitmaps by filename only, then the instance handle can be NULL. It can also be NULL if you wish to load the predefined bitmaps available with Win32. This constructor doesn't call the GetDlgItem() item for you, but requires you to pass in the bitmap window handle directly so the class can work with bitmap windows created using the CreateWindow() function, as well as windows on a dialog box. Take a look at the dialog procedure that uses a CDynBitmap class to manage a bitmap window (download the sample code for a dialog application that uses the CDynBitmap class). 

Adding bitmaps is simple, and both AddBmp() member functions return an index you pass into ChangeBitmap() to display the picture. The destructor cleans up the HBITMAPs added to the class, so you don't need to keep track of them to clean them up. 

The CDynBitmap class is a great starting point for your bitmaps-on-dialog needs. You can easily add a dynamic list for the HBITMAP handling. This example is basic and runs on Windows 98, NT, and CE. Download the complete class code and the sample application code. 


Andy Harding is a software engineer at BSquare Corp. He would like to thank David Brownell, Andrew Tucker, and Steve Makofsky for the help that they have given him. If you have a question for Andy, send it to andyh@bsquare.com
 


c0Title: Changing Window Styles in an MFC Application
c1Code:
 http://www.devx.com/premier/mgznarch/vcdj/1999/jul99/window1.asp 
Changing Window Styles in an MFC Application
By Eduard Koller 

System Notes 
To replicate the steps described in this article, you will need: 
Windows NT4 (any service pack), Windows95 or Windows98 
Visual C++ 5 or 6 
 
In its version of the WinMain() function, MFC registers several standard window classes for you, such as CFrameWnd, CMDIChildWnd and CView. Because you can't easily gain access to MFC's WinMain(), it doesn't seem possible to change the MFC default window styles. You can, in fact, change the styles of CView, the most important preregistered window class in an existing application, and this article will show you how, and how to do it at run time.

Changing styles in a new MFC application

If you're using Visual C++ 6.0, you can change the default window styles of the main frame and MDI child frame windows in the AppWizard's Advanced Options dialog box, available at step 4 in the AppWizard. Unfortunately, you can't access the view's style at this time. 

Changing styles in an existing MFC application 

To change the window attributes used by an application created with AppWizard, you need to override the window's PreCreateWindow() virtual member function. PreCreateWindow() allows an application to access the creation process normally managed internally by the CDocTemplate class. The framework calls PreCreateWindow() just prior to creating the window. By modifying the CREATESTRUCT parameter to PreCreateWindow(), your application can change the attributes used to create the window. 

This approach is suitable for both main frame and view, as well as for any other MFC-based window. 

To change the window attributes in your class derived from CFrameWnd or CView, you simply override the PreCreateWindow() function. For example: 

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT & cs)   
{
  if (!CMDIFrameWnd::PreCreateWindow(cs))
    return FALSE;
  cs.style &= ~WS_SYSMENU;
  return TRUE;   
}

 

creates a main frame without the system menu. 

A little more work is required to change the window style of a child window in a multiple document interface (MDI) application. By default, an MDI application created with AppWizard uses the default CMDIChildWnd class defined in MFC. To change the window style of an MDI child window, you must derive a new class from CMDIChildWnd and replace all references to CMDIChildWnd in your project with references to the new class. 

Supposing your MDI child class is defined as: 

class CMyChildWnd : public CMDIChildWnd

 

the code for creating your child without the maximizing button is: 

BOOL CMyChildWnd::PreCreateWindow(CREATESTRUCT& cs) 
{ 
    cs.style &= ~WS_MAXIMIZEBOX; 
    return CMDIChildWnd::PreCreateWindow(cs); 
}

 

Changing styles at run time 

The window styles specified when an application creates a view are fixed throughout its lifetime. When it creates a new view, Windows stores window-style information in several internal data structures. Windows refers to these data structures when it performs window management tasks, including painting the window. 

If an application calls the SetWindowLong() function to change the window style dynamically, the new information is not always reflected in the internal data structures. For example, an application can't effectively change the ES_AUTOHSCROLL style of an EditView. The same problem occurs when trying to dynamically change the style of an edit control in a dialog box. An application can perform this function in two different ways: 

The application creates two edit boxes with different styles, and shows the edit box with the desired style and hides the other. 
The application destroys the existing edit box and creates a new edit box in its place. 
The first method, which is simple to implement and runs efficiently, requires memory space to store two copies of the edit box contents, and unfortunately cannot be applied to the case of an EditView To change the styles of a CView-derived view after it is created, you can apply the second method from above, performing the following steps: 

Find out the properties (size and different styles) of the current view. 
Create a new window, which should be initially invisible, having the same properties as the current view, except the styles you want to modify. 
If necessary, adjust some attributes of the new window, other than those set on step 3. (For example, if your view is derived from CEditView, and the user has already typed some text inside, copy the text from the current view to the new window - which, in this case, would be created from the "EDIT" window class). 
Detach the old window from the view object. 
Subclass the new window, created at step 2 (i.e., attach it to the view object). 
Show the new window. 
Destroy the old window. 
Following are the implementation details: 

The window properties of the current view are: 
CWnd:GetStyle() returns the window style; modify this style by removing the WS_VISIBLE attribute and performing any changes you intend for the view. 
CWnd::GetWindowRect() copies the dimensions of the bounding rectangle of the CWnd object to a Crect object or a RECT structure. The dimensions are given in screen coordinates relative to the upper-left corner of the display screen. To create the new window, you'll need its position relative to its parent window. Thus, you have to call the GetParent()->ScreenToClient() for your view. 
Creating a new window:
Use the ::CreateWindow() function, with the following arguments: 
lpClassName: "EDIT" 
lpWindowName: for an edit control. This is the text contained in the edit box; you can leave it blank, because you'll set this member in step 3. 
dwStyle: the window style determined above. 
x, y, nWidth, nHeight: the size and position relative to its parent window, as computed above. 
hWndParent: the handle to the parent window, obtained with GetParent()->GetSafeHwnd(). 
hMenu: the ID of the window to be replaced, obtained with GetDlgCtrlID(). 
hInstance: the handle to the application instance, obtained with AfxGetInstanceHandle(). 
lpParam: set this member to NULL. 
Duplicating the text from the old window into the new one:
Obtain the text from EditView by calling CWnd::GetWindowText(), and its length by calling CEditView::GetBufferLength(). After allocating a buffer to temporarily keep the text, put the text into the new window created in step 2 using CWnd::SetWindowText(). 
Detaching the old window from the view object:
When the framework creates a CEditView object, the window is subclassed, i.e., its WndProc is replaced with a new window procedure that translates the messages into calls to the appropriate CWnd-derived class member functions like CYourWnd::OnCreate() and CYourWnd::OnPaint().
Call CWnd::UnsubclassWindow() to set WndProc back to its original value and detach the window identified by HWND from the CWnd object. If you don't call CWnd::UnsubclassWindow(), you'll get an assertion failure when destroying the old edit window. 
Subclassing the new window:
Using CWnd::SubclassWindow(), attach the window you created at step 2 to the MFC EditView object. 
    6. Reveal the new window:


Use CWnd::SetWindowPos() to do this. To keep the original position, the last argument should be set to SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW. To make this change effective, call CWnd::UpdateWindow(). 
Now, destroy the old window, using ::DestroyWindow(). 
 
  
A minimal sample 

You can test this method by creating a simple text editor, which implements the "word wrapping" feature. 

Using AppWizard, create a multiple document MFC application we'll call "Notes." In step 6 of AppWizard, be sure to change the base class of CNotesView from CView to CEditView. A CEditView object is a view that, like the CEdit class, provides the functionality of a Windows edit control and can be used to implement simple text-editor functionality. After selecting "Finish," AppWizard will create a Notepad - much like the text editor, but with a multiple document interface. 

The edit control does not have an ES_WORDWRAP style. The word wrapping can be enabled by using the ES_AUTOHSCROLL and WS_HSCROLL styles. ES_AUTOHSCROLL tells the edit control to scroll the text horizontally, when necessary, as the user enters text. However, if ES_AUTOHSCROLL is not specified, the edit control cannot scroll horizontally. For multiple-line edit controls without ES_AUTOHSCROLL, the text wraps to the next line when the user enters more text than can be displayed on a single line. If ES_AUTOHSCROLL is specified for a multiple-line edit control, the text will not wrap; the control simply scrolls horizontally when the user enters more text than can be displayed on a single line. 

ES_AUTOHSCROLL is automatically applied to an edit control that has a WS_HSCROLL style. In other words, any edit control that has a horizontal scroll bar automatically scrolls horizontally. 

Now, add the user interface to dynamically switch word wrapping ON or OFF: 

In the ResourceView open the IDR_NOTESTYPE menu and add a new menu item to one of its popups (e.g., to the "Edit" popup). Name this Item "Word Wrap," give it an ID: ID_WORDWRAP, then use ClassWizard to add a message handler to it. Let's name this CNotesView::OnWordwrap(). 
Add to CNotesView a bool member m_bWordWrap to keep the current state. 
In the function CNotesView::PreCreateWindow(), set this member to true immediately below this line: cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL);// Enable word-wrapping
bWordWrap = TRUE

 

Implement the function CNotesView::OnWordwrap() as shown below. void CNotesView::OnWordwrap() 
{
// Step1:

  DWORD dwNewStyle = GetStyle() & ~(WS_VISIBLE | 
  		WS_HSCROLL | ES_AUTOHSCROLL); 
  if (m_bWordWrap)
    dwNewStyle |= WS_HSCROLL | ES_AUTOHSCROLL;

  CRect rect;
  GetEditCtrl().GetWindowRect(&rect); 
  CWnd *pParent = GetParent(); 
  pParent->ScreenToClient(&rect);

// Step2:
  UINT nId = GetDlgCtrlID();
  HWND hWndNew =::CreateWindow("edit", "", dwNewStyle, 
rect.left, rect.top, rect.right - rect.left, 
rect.bottom - rect.top, pParent->GetSafeHwnd(), 
(HMENU)nId, AfxGetInstanceHandle(), NULL);

// Step3:

  UINT nTextLen = GetBufferLength(); 
  char *pszText = new char[nTextLen + 1]; 
  GetWindowText(pszText, nTextLen); 
  pszText[nTextLen] = 0;
  
  SetWindowText(""); 
  ::SetWindowText(hWndNew, pszText); 
  delete[] pszText;

// Step4:

  HWND hWndOld = UnsubclassWindow();
  ASSERT(m_hWnd == NULL); 

// Step5:

  SubclassWindow(hWndNew);
  ASSERT(m_hWnd == hWndNew);

// Step6:

  SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | 
  		SWP_NOACTIVATE | SWP_NOZORDER | 
		SWP_SHOWWINDOW | SWP_DRAWFRAME); 
  UpdateWindow();

// Step7:

  ::DestroyWindow(hWndOld);
  m_bWordWrap = !m_bWordWrap;

}

 

Finally, you can override the OnUpdateWordWrap() function to set a checkmark at the menu item to reflect the current state (on/off) of the wrapping. 

Conclusion 

You can change the window styles for a view in an MFC application during the view's construction, or at run time. To change the window attributes in your class derived from CView during its construction, you simply override the PreCreateWindow() function. To change the style of a CView-derived view after it is created, you must destroy the associated edit control, and create a new edit and attach the new edit to the view. 


c0Title: Implement a Circular Iterator
c1Code:
Usually, you start an iterator at the beginning and let it progress to the end. But what if you want to go through the container over and over again, just as a circular buffer does? For that, you need a circular iterator. 

Because you'll use the iterator for many different types of STL containers, it has to be a template. Even if you only want to use the iterator for vectors, the compiler considers vector<int> and vector<string> different types; you still need to templatize the iterator: 



template<typename T>
class const_circular_iter : public 
   std::iterator<std::forward_iterator_tag, T::value_type>
{  


You use the std::iterator<> base class to tell the compiler that the circular iterator has all the capabilities of a forward iterator and can be used wherever one is required. The class is called "const_circular_iter" because you can only read values from it�you can't modify the container: 



protected:

   T::iterator begin;
   T::iterator end;
   T::iterator iter;

This process behaves like a normal iterator until it reaches the end, where it jumps back to the beginning. This means you'll have to know where the end and the beginning are, and where you are now. The three iterators handle that. You might think that if you hold a reference to the container you're iterating through, you can get by without begin and end. True, but that requires you to step completely through the container. Doing it my way enables you to loop over a few elements in the middle of a larger container and to use iterators that don't point into a container. 

Yes, I did cringe over making data elements protected instead of private, but if you want to derive a modifiable version of the circular iterator from this implementation, using protected saves a lot of extra work: 



public:
   const_circular_iter(T& t) : iter(t.begin()), 
      begin(t.begin()), 
      end(t.end()) {}; 
   const_circular_iter(T::iterator b, T::iterator e)          
      : iter(b), 
      begin(b), end(e) {};

Few classes can get by without constructors, and here are ours. You can initialize the class with the container you'll loop over, or with just iterators for the beginning and end: 



const_circular_iter<T>& operator++()
{   
   ++iter;
   if (iter == end)
      iter = begin;
   return(*this);
}

The prefix increment operator is the heart of the class. It increments the internal iterator, and at the end, points back to the beginning. From here, the rest is essentially boilerplate and buck passing: 



const_circular_iter<T> operator++(int)
{
   const_circular_iter<T>   t=*this; 
   ++(*this);
   return(t);
}

const T::value_type operator*() const 
   {return (*iter);}

bool operator==(const const_circular_iter<T>&   
   rhs) const 
   {return (iter == rhs.iter);}

bool operator!=(const const_circular_iter<T>&   
   rhs) const 
   {return ! operator==(rhs); }
};

The postfix increment operator delegates much of its work to the prefix increment. The dereference operator passes its work onto the internal iterator dereference operator, the inequity operator uses the equity operator, and that's it. 

This sample program puts three values into a vector, then iterates through them and prints them, wrapping around the end of the vector by calling the increment operator more times than you have values in the vector: 



#include <iostream>
#include <vector>
#include "circular.h"

using namespace std;

int main(int argc, char* argv[])
{
   vector<int>      v;
   v.push_back(1);
   v.push_back(2);
   v.push_back(3);

   const_circular_iter<vector<int> > out (v);    // or 
   "out(v.begin(), v.end());" 
   cout << *out ++;
   cout << *out ++;
   cout << *out ++;
   cout << *out ++;
   cout << *out ++ << endl;
   
   return 0;
}

This prints "12312." 


Send Your Tip
If it's cool and we publish it, we'll pay you $25. If it includes code, limit code length to 20 lines if possible. Be sure to include a clear explanation of what your tip does and why it's useful. Internet: vcdjedit@fawcette.com. Post: Lauren Kennedy, Fawcette Technical Publications, 209 Hamilton Avenue, Palo Alto, CA, USA, 94301-2500. Please include your mailing address with your submission. 

James M. Curran is a senior software engineer for e-Commerce Solution in New York City. Reach him at JamesCurran@mvps.org


c0Title: Construction of a Variant Type
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/1999/octmag99/beveridge1.asp
Construction of a Variant Type
System Notes 
To replicate the steps described in this article, you will need: 
Visual C++ 5.0 SP3 or later 
 

A design technique for creating weakly-typed variables, delaying typing decisions, and more

By Jim Beveridge 
One important feature of C++ is that it is a strongly typed language. However, if you've worked in weakly-typed languages, you know there are some jobs where all that type safety just gets in the way. In this issue we'll look at the construction of a variant type that allows you to mostly ignore the data type issues happening beneath you. If you have used VARIANTs in COM before, the fundamental concept is almost identical. However, the C++ interface shown here makes type conversions implicit rather than explicit. Here is an example of a variant in action: 

MyVariant m = 5;
MyVariant n = "3";
long d = m * n;
printf("%ld\n", d);

 


If you run this code segment, the result is: 

15

 


This is interesting because the code multiplies a number times a number represented as a string and comes out with an intuitively correct answer instead of a "compiler correct" answer. Clearly, there is more going on here than simple type coercion. 

Let's look at how to build the class MyVariant to support this functionality. To make this happen, we'll use some of the more obscure C++ tools for class construction and test your memory of C++ trivia. 

 
Background  


If you've never seen variant types (hereafter referred to as just "variants") before, it can be difficult to understand why you might need variants when you have templates at your disposal. While both templates and variants allow you to defer deciding on the exact type, the difference is in how long you can delay the decision. 

When you write a class template or a function template, you defer the decision of the exact type until a developer uses the code. With function templates (as opposed to class templates), the compiler may automatically infer how to instantiate the template, but the decision is still made by compile time at the latest. 

With variants, a final decision is never made. A single variant can masquerade as different types even at run time, switching from a long to a string to a bool. For example, one common programming challenge is how to return a value from a function while returning error information in case of a problem. By using a variant as the return value, the variant will carry type information to indicate whether a return value is an error or a legal value. 

 
Representing the data  


One of the first problems to overcome is how to represent the data. The class must be capable of keeping track of the data type of the currently stored element. The class must also leave enough space for all of the element types that can be stored within it. Let's try to build such a class for a variant type that can hold either a CString (from MFC) or a long. For the first try, we can use a simple class: 

class MyVariant
{
public:
    int	m_Type;
    long	m_LngVal;
    CString	m_StrVal;
};

 


This class has the basic elements. It can hold either kind of data and it leaves room for type information. Unfortunately, as support for new data types is added to the class, the size of the class will become larger and larger. The union was designed to solve this problem. In addition, a naked int is a poor choice for the type because m_Type only has a small number of legal values. Therefore, an enum would be a better choice. Here is a revised version (header files omitted). 

class MyVariant
{
public:
    enum EVariantType
    {
        VAR_I4,
        VAR_CSTR
    };

    EVariantType    m_Type;

    // Note that this is an anonymous
    // union, which is not C++ standard.
    union 
    {
        CString m_StrVal;
        long  m_LngVal;
    };
};

 


We could add as many types as needed to this variant type. To solve the problem of returning error values described above, we could add VAR_ERR to the list of types in the num. 

The class above would be a fine representation except for one thing: it doesn't compile. The line that says "CString m_StrVal;" generates an error. Because the various members of a union all share the same physical space, the compiler can't call the constructors for the members because they would interfere with each other. Therefore, variables are not allowed to be members of a union if they have non-trivial constructors or copy constructors. In this case, CString has a constructor and a copy constructor and consequently is not a legal member of the union. 

The solution is to resort to bit-wise trickery and use the following declaration instead: 

char	m_StrVal[sizeof(CString)];

 


This declaration leaves enough room to hold a CString without actually declaring one. In a moment, you'll see how to access this member variable. 

 


 
Construction  


The first thing to write for any class is a constructor. In this case, the "correct" initial value is a matter of some debate. The strictly correct thing to do would be to set the type to "null" or "empty," but that causes a variety of messy error conditions if someone tries to use it that way. Because we'd like to avoid that mess for this example, we'll initialize the variant to an empty string, where the type is VAR_CSTR (for CString) and the union is initialized to an empty CString. 

MyVariant::MyVariant()
{
    m_Type = VAR_CSTR;
    new(&m_StrVal) CString;
}

 


The call to operator new is an obscure usage called "placement new." This version of new is used when you already have a block of memory and want to construct that block as a particular kind of object. Placement new is defined in the header file <memory>. 

Now we can create an empty MyVariant, but can't put anything in it. Let's add a conversion constructor for long: 

MyVariant::MyVariant(long nSrc)
{
    m_Type = VAR_I4;
    m_LngVal = nSrc;
}

 


This conversion constructor shows the essence of how the class works. It would be called by a statement like: 

MyVariant myvar(5);

 


The compiler notices that the argument to the constructor is a long and automatically calls the appropriate conversion constructor. This is critical to making the variant work. The only way you can know what kind of data is being stored in a variant is by which function the compiler calls. Generally, the compiler makes this decision during an implicit conversion, but the decision can be made explicit by using a static cast. You'll see this shortly. 

Because this class also needs to support strings, we'll add a conversion constructor for strings: 

MyVariant::MyVariant(const CString& strSrc)
{
    m_Type = VAR_CSTR;
    new(&m_StrVal) CString;
    // This cast would be reinterpret_cast
    // if you use the new cast operators.
    (CString&)m_StrVal = strSrc;
}

 


Remember that the default constructor is not called when another constructor is called, so the content of the variant at the beginning of this function is essentially garbage. As in the default constructor, we set the type and initialize the CString. The third line shows how we access the problematic StrVal as a CString instead of as an array of bytes. Since a reference can be an lval, we coerce the member variable to be a reference to a CString. The net result is that the memory behaves exactly as if it were of type CString. Note that trying to cast to a CString instead of a CString& will give the wrong result. 

 
Destruction  


Now that we have safely constructed the object, the next step is to safely tear it down. To properly destruct the object, it is necessary to examine the type of the object and take appropriate action. There will be many places where we will need to tear down the object, so we factor the code into a single member function called Clear(). 

MyVariant::~MyVariant()
{
    Clear();
}

void MyVariant::Clear()
{
    if (m_Type == VAR_CSTR)
        ((CString&)m_StrVal).~CString();
}

 


No action is necessary to destruct a long, so Clear() checks the type and takes appropriate action only in the case of a string. If the variant is currently representing a CString, then Clear() calls the destructor for a CString and cleans up. 

 
Assignment operators  


The third and final requirement for this class is to write assignment operators. The assignment operators for long and CString are very similar to the conversion constructors, but the assignment operator for another MyVariant is a little more complex: 

void operator=(const MyVariant& src)
{
    Clear();
    m_Type = src.m_Type;
    // Use the appropriate object's 
	// assignment operator
    switch (m_Type)
    {
    case VAR_CSTR:
        {
        new(&m_StrVal) CString;
        (CString&)m_StrVal = 
			(CString&)src.m_StrVal;
        }
        break;
    case VAR_I4:
        m_LngVal = src.m_LngVal;
        break;
    }
}

 


The first job is done by Clear(), which destructs anything currently stored within *this. Next, the new type is copied over. Finally, depending on the type of source variant, the appropriate member of the union is accessed directly and the assignment operator is called. For a long, that would be a raw byte copy, but a CString would use its own assignment operator to handle reference counting. The goal is to do enough work to figure out how to let the compiler take over the remainder. 

 
Accessors  


To make this variant class usable, it's necessary to be able to get data out of it after putting data in. Because this class is very simple and has minimal ambiguity, I will use conversion operators instead of GetXXX() functions. 

The conversion operators are where the magic happens. As in the case of construction, the compiler will call what it believes to be the most appropriate conversion operator function for a given context. Depending on which function is called, MyVariant needs to return data in that format if such a thing can be created from the current format of the data. Given that the data types are limited to string and long, the conversion matrix is straightforward. Numbers can always be converted to strings. Some strings can be converted to numbers; we'll return zero for any that can't. 

The conversion operator for long is shown below. See Listing 1 at the end of this article for the conversion operator for CString. 

MyVariant::operator long()
{
    switch (m_Type)
    {
    case VAR_CSTR:
        return atof((CString&)m_StrVal);
    case VAR_I4:
        return m_LngVal;
    }
    return 0;
}

 


  
 

 
Variants in action  


Now we have enough code written to actually do something useful. (See Listing 1 for the complete listing.) The code from the beginning of the article will actually execute successfully: 

MyVariant m = 5;
MyVariant n = "3";
long d = m * n;
printf("%d\n", d);

 


Line 1 constructs a MyVariant using the conversion constructor for long. (Note: It really does use the conversion constructor, not the assignment operator, regardless of the way it is written. This behavior is part of the C++ standard and is correct behavior.) Line 2 constructs a MyVariant using the conversion constructor for CString. Line 3 uses the built-in binary arithmetic operator*(), and the compiler is able to unambiguously use the long value of m and n. 

Unfortunately, all is still not quite perfect. If we tried to use "plus" instead of "times," as in "long d = m + n," the compiler wouldn't know whether you mean arithmetic addition or string concatenation. It needs a hint to help figure it out. 

CString s = CString() + m + n;

 


After this statement, the value of s1 would be "53" because the values would be concatenated. 

For another example, consider the case of a function that can look up multiple addresses based on either an index or a name. One solution is to provide two functions: one that works by name and one that works by index. The alternative is to pass in an array of variants so the caller can request both at the same time. The function can then look at each element of the array to determine whether the element is a name or an index. 

typedef vector<MyVariant> RequestVec;

bool LookupAddresses(
          const RequestVec& requests,
          vector<Address>& addresses)
{
    for (int i=0; i<requests.size(); i++)
    {
        if (i->m_Type == VAR_CSTR)
        {
            CString strSearchName = 
							requests[i];
            // ...
        }
        else
        {
            long nSearchName = requests[i]; 
            // ...
        }
    }
}

 


 
Limitations  


By nature, variant types will always be slower than the raw data types that a variant can represent. However, the question most developers should ask is not, "Is it fast?" but instead, "Is it fast enough?" In the address example above, the time required to build the variants will probably be negligible in contrast to the time the search will take, even if the request set is very large. In Visual Basic, variants are often pegged as a performance bottleneck. C++ developers have more control and should be able to use variants where it is easy, and bare-metal performance-oriented classes when appropriate. 

Variant types do not work well everywhere. They depend on having internal support for each data type they can encapsulate. Therefore, most implementations of a variant support the standard types such as long, short, and double. A few implementations also support some form of strings. Microsoft's implementations support IDispatch and IUnknown. However, if you want variant support for a user-defined type (i.e., a class that you define), you won't be able to do so with most variant implementations unless you code it as a COM object or do a lot of casting with void pointers. 

 
Summary  


In this issue we've looked at a design technique rarely used in the C++ world but common in high-level languages. The creation of a variant type provides some insight into language features such as unions and placement new that are not commonly encountered in everyday coding. The variant can be used to create weakly-typed variables, delay typing decisions, and pass heterogeneous data. 

Next time we'll look at the variant types built into Visual C++, which are significantly more powerful than the simple variant class presented here. We'll also look at the use of variants in Automation. 

#include <afx.h>
#include <vector>

using namespace std;

class MyVariant
{
public:

    MyVariant()
    {
        m_Type = VAR_CSTR;
        // Initialize to an empty string;
        new(&m_StrVal) CString;
    }
    MyVariant(const MyVariant& src)
    {
        m_Type = VAR_I4;
        *this = src;
    }
    MyVariant(long nSrc)
    {
        m_Type = VAR_I4;
        m_LngVal = nSrc;
    }
    MyVariant(const CString& strSrc)
    {
        m_Type = VAR_CSTR;
        new(&m_StrVal) CString;
        (CString&)m_StrVal = strSrc;
    }
    ~MyVariant()
    {
        Clear();
    }
    void operator=(const MyVariant& src)
    {
        Clear();
        m_Type = src.m_Type;
        // Use the appropriate object's 
	// assignment operator
        switch (m_Type)
        {
        case VAR_CSTR:
            {
            new(&m_StrVal) CString;
            (CString&)m_StrVal = 
				(CString&)src.m_StrVal;
            }
            break;
        case VAR_I4:
            m_LngVal = src.m_LngVal;
            break;
        }
    }
    void operator=(long nSrc)
    {
        Clear();
        m_Type = VAR_I4;
        m_LngVal = nSrc;
    }
    void operator=(CString& strSrc)
    {
        Clear();
        m_Type = VAR_CSTR;
        new(&m_StrVal) CString;
        (CString&)m_StrVal = strSrc;
    }

    operator long()
    {
        switch (m_Type)
        {
        case VAR_CSTR:
            return atof((CString&)m_StrVal);
        case VAR_I4:
            return m_LngVal;
        }
        return 0;
    }

    operator CString()
    {
        switch (m_Type)
        {
        case VAR_CSTR:
            return (CString&)m_StrVal;
        case VAR_I4:
            {
            CString str;
            str.Format("%d", m_LngVal);
            return str;
            }
        }
        return CString();
    }

protected:
    void Clear()
    {
        if (m_Type == VAR_CSTR)
            ((CString&)m_StrVal).~CString();
        // The variant is in an illegal state
        // at this point, which is why Clear()
        // is in the "protected" section.
    }

    enum EType
    {
        VAR_I4,
        VAR_CSTR
    };

    EType   m_Type;

    // Note that this is an anonymous
    // union, which is not C++ standard.
    union 
    {
        char  m_StrVal[sizeof(CString)];
        long  m_LngVal;
    };
};

int main()
{
    MyVariant x = 9;
    MyVariant y = "7";

    long z = x * y;
    printf("%d\n", (long)z);

    CString s1 = CString() + x + y;
    printf("%s\n", s1);

    for (MyVariant n="1"; n<=10; n = n+1)
        printf("%d\n", (long)n);
    return 0;
}

 


 
Jim Beveridge is an independent consultant specializing in software architecture, design, and project management. He is the author of Multithreading Applications in Win32 from Addison-Wesley and a frequent speaker at the Visual C++ Developers Conferences. Reach him at jbeveridge@fawcette.com. 
 


c0Title: Constructor Not Connecting
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/07jul00/ap0007/ap0007.asp
Supposed, Former, Entry-Point Junkie 
by Andy Harding 


   Q. Constructor Not Connecting 
I'm having a problem with a constructor for my class, which is ignored when it's created as a global variable in a Windows application. How can this be? I've included my source code (see Listing 1). Also, can you explain why I had to place "int main() {return 0;}" in my source code, but only so the debug version would link? I even typed in WinMain() as my starting point, but the code still doesn't work. 
What you need:
Visual C++ 6.0 SP3  
 
A. The problem isn't in the source code; it's how you start the program. When you specified WinMain() as the entry point to your program, you inadvertently skipped all the startup code and initializing the standard libraries provide, as well as any construction code for initializing static global classes. 

Your code provides an excellent example of why specifying an entry point isn't recommended. When you run your application, two message boxes come up showing the value of the integer data member, part of CTestClass. Two instances of CTestClass call the single argument constructor, CTestClass (27). The first instance is a static global variable and the second is a local variable. When the global instance displays the data that should have been calculated in the constructor, it returns a 0 (see Figure 1), while the local instance returns an 84, the correct value (see Figure 2).     
Figure 1 Results of the Test Class Constructor Called From a Global Instance Click here.

 



Fixing your code is simple�don't specify the entry point into your application. The entry point for Win32 applications should be WinMainCRT Startup. The standard libraries provide this function, the Windows application default. By not specifying an entry point, you allow the linker to choose the correct one for you. If you're using the integrated development environment (IDE) to handle your project settings, you can change them by selecting Project Settings, then clicking on the Link tab and selecting Output from the Category option (see Figure 3). Under Entry-point symbol, you'll see the edit box containing the function name for your custom entry point. Remove this function name. The /ENTRY:Func in the Project Options edit box disappears after you delete the entry, enabling the linker to use the default entry point.     
Figure 2 Results of the Test Class Constructor Created as a Local Instance Click here.

 



But what if you have a good reason not to use the default entry point? If the size of your ActiveX control or executable is important to you, you can save a few kilobytes by not including the startup code in the default entry point. If you're writing Active Template Library components that have to be downloaded, saving a few kilobytes might also be important to you. Microsoft thought it was important enough that they provided the #define, _ATL_MIN_CRT. When you use _ATL_MIN_CRT, the ActiveX control startup code gets stripped out, but you might want to use this, so you should know its restrictions.     
Figure 3 Don't Specify the Entry Point Click here.

 



First, you can't have static global objects requiring constructors, as you've just seen. Second, you won't be able to use C++ exception handling. Third, the standard library memory-allocation functions won't work correctly. These routines expect the startup code to initialize the heap. And last, many standard library string functions require some initialization from the startup code. 

The string functions problem explains why you had to include a dummy main function in your program. The _stprintf() macro you're using calls the correct version of sprintf() for you. The printf() string function requires some initialization to work properly. A better alternative might be wsprintf(), part of the Windows OS and already initialized before your program runs. The Windows header files provide the same sort of help the TCHAR macro _stprintf() gives, but require no overhead in your program. Given ActiveX controls and Windows applications require Windows to run, you should be able to live with this change. 

How then can you tell if you're using functions that require initialization by the startup code? If you get this linker error, you've used a function that needs the startup code: 



LIBCMT.LIB(crt0.obj) : error LNK2001: 
   unresolved external symbol _main

This isn't the most descriptive error message around, but if you know why it comes up, it can work for you. Please don't create a dummy main, which only makes it harder to track down related problems in the future. This linker warning is your friend and alerts you to problems before your best customer calls complaining about your ActiveX control's weird behavior. Practice "safe coding" techniques, and you'll be much happier. 

It's important to use the provided startup code, if possible. You've been using this functionality since you started coding, so don't stop now. Microsoft paid a bunch of programmers a lot of money to give you the default startup code. Is it worth your time to create it again? 


Andy Harding is a software engineer at BSquare Corp. He would like to thank David Brownell, Andrew Tucker, and Steve Makofsky for the help that they have given him. If you have a question for Andy, send it to andyh@bsquare.com
 


c0Title: Container classes in ATL
c1Code:
 http://www.devx.com/premier/mgznarch/vcdj/1999/julmag99/atlcontainer1.asp 
When you need simple, tight code to contain data

By Richard Grimes 
System Notes 
To replicate the steps described in this article, you will need: 
Win9X 
Windows NT4 
Visual C++ 6.0 
 
Every software project needs a container at some point in its development to hold items of the same type. While the simplest type of container is a static-sized C++ array, it's not necessarily the best choice, because at compile time you won't know exactly how many items you'll need to put in the array. This could make you overly cautious, causing you to overestimate and waste memory. 

A better approach is to create arrays on the heap at run time by allocating with new or malloc(), so you know how many items the container will hold and you can allocate only as much memory as is needed. However, because this memory is allocated on the heap, you'll need to free it when the array is no longer used. If you use malloc(), you'll also need to ensure that the items inserted into the array are correctly destroyed. In addition, because you decide the size of the array when you allocate it, if you later decide that the array is too small, you'll need to reallocate it. 

The solution is to use a container class that performs all this functionality for you. There are several options. Let me state up front, however, that I wouldn't use MFC's container classes CArray<>, CList<>, and CMap<> for two reasons: first and foremost, this is an ATL article, and second, if you use these classes in ATL you'll pull in code from the MFC libraries, either from the static libraries or the vast bulk of MFC's runtime DLLs. 

The point about static-linking MFC is important because MFC can boost the size of a COM server, making it unsuitable to serve lightweight components. Also, concern about dynamic linking should not be dismissed. Although most Windows systems will have the MFC runtime installed, either through installation applications that demand them, or by tools used by the operating system itself, the main problem is that MFC and the DLLs each come in several versions. So if your code dynamically links to MFC, how can you be sure that your customer has installed the correct version of the MFC runtime? This is the code versioning problem that COM strives to solve. 

The standard template library (STL) isn't hazard-free either. The version delivered with Visual C++ isn't thread-safe, so you have to make sure that you use STL containers in a thread-safe way. In addition, STL uses C++ exceptions, and exception handler code bloats the size of your code. If you compile code that uses STL but turn off exception support, it will compile but you will get warnings. The warnings remind you that somewhere, some code could throw a C++ exception. If not caught, the exception will be propagated out of your code and passed to the user. 

The best option in my opinion is to use ATL's container classes. I'll spend the remainder of this article explaining what they are. 

 
ATL container classes  

ATL's container classes are called CSimpleArray<> and CSimpleMap<>. Why simple? They don't have all of the support you get with STL containers: there are no iterators, you have no choice over how the container's memory is allocated, and ATL doesn't provide algorithms that can be used to manipulate the containers and the data in them. Furthermore, you cannot alter how the data is stored and accessed. (This means you can't make informed choices like you can with STL, which lets you choose a container like std::vector<> when you primarily need random access, or std::list<> when you want serial access.) 

Simplicity is an advantage. These are lightweight containers that don't need C++ exception support, but do provide sufficient functionality to hold collections and to search for and access that data. However, be aware that they're still not thread-safe. Thus, if you share a container between two threads (e.g., a multi-threaded apartment object can be accessed by two threads at a time), one thread could attempt to access a member while another is writing it. It is up to you to ensure that this never happens (by using appropriate locking). 

 
Arrays  

Let's take a look at these classes. The first, CSimpleArray<>, is shown in the following code. It is a template with a parameter of T, the type of data that is held. 

template <class T>
class CSimpleArray
{
public:
	T* m_aT;
	int m_nSize;	
	int m_nAllocSize;

	CSimpleArray();
	~CSimpleArray();
	int GetSize() const;
	BOOL Add(T& t);
	BOOL Remove(T& t);
	BOOL RemoveAt(int nIndex);
	void RemoveAll();
	T& operator[] (int nIndex) const;
	T* GetData() const;
	void SetAtIndex(int nIndex, T& t);
	int Find(T& t) const;
};

 

The data is held in an array called m_aT, which you can access either directly (the member is public) or via the [] operator. Thus you can write code like this:

CSimpleArray<CComBSTR> colours;
CComBSTR bstrRed = L"Red";
CComBSTR bstrGreen = L"Green";
CComBSTR bstrBlue = L"Blue";

colours.Add(bstrRed);
colours.Add(bstrGreen);
colours.Add(bstrBlue);

_tprintf(_T("first colour is %S\n"), colours[0]);
_tprintf(_T("second colour is %S\n"), colours.m_aT[1]);
_tprintf(_T("third colour is %S\n"), colours.GetData()[2]);
 

Note that I have used variables because Add() takes a reference, not a constant value. 

It is worth investigating what Add() does to understand how you can use it. First, it checks to see if there is memory allocated to hold the data. If there isn't, CRT realloc() is used with an exponential algorithm so that each time realloc() is called, it will double the amount of memory requested (the first allocation asks for space for one item, the second one asks for space for two, then four, and so on). If you add 512 items you will have 10 reallocations; if you want space for 513 items you will get enough memory for 1,024 items. It is worth pre-allocating the space if you know how many items you will put into the array: 

colours.m_nAllocSize = 3;
colours.m_aT = static_cast<CComBSTR*>
			(malloc(colours.m_nAllocSize * 
			sizeof(CComBSTR)));
 

This will allocate space for three CComBSTRs that are uninitialized. If you do this, make sure you use malloc() rather than new. After checking to see if there is enough space for the new item, Add() will call SetAtIndex(). This uses the placement new operator of a nested class called Wrapper to initialize the array item. It does this with the item's copy constructor. In the example above CComBSTR(CComBSTR&) will be called on the uninitialized item. If the type doesn't have a copy constructor (a C++ base type, for example), the compiler will provide a shallow copy, so you can do this: 

CSimpleArray<long> arr;
for (long lVal = 10; lVal < 20; lVal++) 
	arr.Add(lVal);
lVal = 10;
arr.Add(lVal);

 

Note that I add the value 10 twice in this code. The class doesn't care about multiple items that have the same value. You can use Find() to find a particular item by value, and this will return the index of the first item with this value. So, using the example above: 

CComBSTR bstrSearch = L"Orange";
if (colours.Find(bstrSearch) == -1)
	_tprintf(_T("%S is not a primary 
			colour\n"), bstrSearch.m_str);
else
	_tprintf(_T("%S is a primary colour\n"), 
		bstrSearch.m_str);

 

This method assumes that the items you have put into the array have an operator==() defined, otherwise the compiler will do a bitwise compare. You can remove items from the array by specifying either the item or its index. If you specify an item value, Find() will be called to find the first item with this value. In both cases, memmove() is called to remove the item and to ensure that the memory used by the array is contiguous. This is useful because it means that you can use CSimpleArray<> to hold the items used to initialize one of ATL's enumerator classes (as I mentioned in my ATL column in the April/May issue). 

It can be frustrating to place literal values into CSimpleArray<> because Add() takes a reference. To get around this, ATL defines a derived class called CSimpleValArray<> as shown in code below: 

template <class T>
class CSimpleValArray : public CSimpleArray< T >
{
public:
	BOOL Add(T t);
	BOOL Remove(T t);
	T operator[] (int nIndex) const;
};
Using this you can add literal values:
CSimpleValArray<int> primes;
primes.Add(2);
primes.Add(3);
primes.Add(5);
primes.Add(7);
_tprintf(_T("third prime is %ld\n"), primes[2]);

 

 
Maps  

A map is an associative container, that is, it associates a value with a key. The convention in STL is to use the key as the parameter to operator[](), for example: 

CComBSTR bstrName = L"Richard Grimes", bstrAddress;
bstrAddress = customers[bstrName];

 

However, this is not the approach taken by CSimpleMap<>. As you can see from the following code block, you access members with either Lookup() (to get the value associated with a key) or ReverseLookup() (to get a key for a value). Both methods return by value, so if large objects are added to the map, an expensive copy is made. You can also search the map for a particular key or value (FindKey() and FindValue()), which will return an index. 

template <class TKey, class TVal>
class CSimpleMap
{
public:
	TKey* m_aKey;
	TVal* m_aVal;
	int m_nSize;

	CSimpleMap();
	~CSimpleMap();
	int GetSize() const;
	BOOL Add(TKey key, TVal val);
	BOOL Remove(TKey key);
	void RemoveAll();
	BOOL SetAt(TKey key, TVal val);
	TKey& GetKeyAt(int nIndex) const;
	TVal& GetValueAt(int nIndex) const;
	void SetAtIndex(int nIndex, TKey& key, TVal& val);
	TVal Lookup(TKey key) const;
	TKey ReverseLookup(TVal val) const;
	int FindKey(TKey& key) const;
	int FindVal(TVal& val) const;
};
 

Unlike CSimpleArray<> (which attempts to reduce calls to realloc()), Add() will make the reallocation for every item added to the map. You cannot pre-allocate the memory as with CSimpleArray<>. Note also that the parameters of Add() are passed by value, so you can use literal values: 

CSimpleMap<CComBSTR, COLORREF> colours;
colours.Add(L"Red", RGB(255, 0, 0));
colours.Add(L"Green", RGB(0, 255, 0));
colours.Add(L"Blue", RGB(0, 0, 255));
_tprintf(_T("Green has a value of %08x\n"), 
		colours.Lookup(L"Green"));

 

CSimpleMap<> takes the straightforward approach of holding the keys and values in two arrays allocated with realloc(), so you can also use GetKeyAt() and GetValueAt() to get the key and values at a particular position. Both of these return references, so you can use them to change values in the map: 

// change the value of Green
CComBSTR bstrGreen = L"Green";
int green = colours.FindKey(bstrGreen);
colours.GetValueAt(green) = RGB(0, 128, 0);
_tprintf(_T("Green has a value of %08x\n"), 
		colours.Lookup(bstrGreen.m_str));
 

The pair of lines with FindKey() and GetValueAt() can be replaced with SetAt():

colours.SetAt(L"Blue", RGB(0, 0, 128));
_tprintf(_T("Blue has a value of %08x\n"), 
		colours.Lookup(L"Blue"));

 

CSimpleMap<> has a Remove() method to remove the entire (key, value) pair using memmove() in much the same way as CSimpleArray<>::Remove(). However, if you make a subsequent call to Add(), the memory taken up by the removed item is not reused; realloc() is always called. Clearly, CSimpleMap<> is not the most efficient implementation because it makes many calls to allocate memory and is thus only useful for maps that contain just a few items. 

 
Big buffers  


CSimpleArray<> allocates a block of memory using realloc(). When this buffer is exhausted, Add() will call realloc() again to get more memory. This works for small amounts of data. You can get performance gains by pre-allocating the buffer if you know how many items the array will hold. But what if you want a huge amount of memory, i.e., several megabytes? 

Don't use malloc() here because the CRT code ultimately ends up calling the Win32 function HeapAlloc() to allocate the memory from a private heap. If you specify a huge amount of memory with HeapAlloc(), Win32 will attempt to commit all the necessary memory pages for this request-an expensive mechanism. (Reserving a page tells the system you want to use an address page; committing a page will actually give you access to the physical memory.) Applications that are designed to use large amounts of memory (like databases) typically reserve a range of memory pages to make the access code simple, but only commit the actual memory page they are using. If you commit many pages of memory you are blocking the physical memory from use by other processes, which slows the system down.

To get around this problem Win32 provides a series of API functions to manage virtual memory, and gives you the choice to reserve or commit memory. The ATL class CVirtualBuffer<> (see following code block) is designed to allow access to huge arrays of data using the virtual memory API. 

template <class T>
class CVirtualBuffer
{
protected:
	CVirtualBuffer() {}
	T* m_pBase;
	T* m_pCurrent;
	T* m_pTop;
	int m_nMaxElements;
public:
	CVirtualBuffer(int nMaxElements);
	~CVirtualBuffer();

	int Except(LPEXCEPTION_POINTERS lpEP);
	void Seek(int nElement);
	void SetAt(int nElement, const T& Element);
	template <class Q>
		void WriteBulk(Q& helper);
	void Write(const T& Element);
	T& Read();
	operator BSTR();
	const T& operator[](int nElement) const;
	operator T*();
};

 


You then pass the number of possible items in the array as a parameter of the constructor, which calls VirtualAlloc() to reserve enough memory pages for all the items. Only the first page (or enough pages for one item) is actually committed, the rest are committed when you actually try to write to the memory. How does it know whether the page has been committed? It does this by catching the access violation exception thrown when the code attempts to write to non-committed memory; the Except() function handles this Win32 exception. It is called in the exception handler and the Except() function handles the exception by committing the requested page. Note that because this is Win32-structured exception handling, you don't have the overhead associated with C++ exceptions. 

Except() has an odd way of committing pages. It actually calculates the total number of bytes already in committed pages and then commits a sufficient number of pages to contain that amount of memory. For example, every time Except() is called, it doubles the number of committed pages. This is similar to how CSimpleArray<>::Add() behaves. While I understand the reason for this behavior for small memory allocation, I believe it is excessive for large memory commitments. 

The class maintains a current position that is used with Read() and Write(). The other methods are straightforward except for WriteBulk() and the BSTR conversion operator. WriteBulk() allows you to write a large number of items at one time using a helper class passed by reference as the parameter. This should implement an () operator with the following prototype: 

T* operator()(T* pCurrent);

 


Here T is the type that your CVirtualBuffer<> uses. The method should write whatever data it wishes to the memory pointed to by pCurrent, and return the address of the memory immediately after the last item written. For example, if you use an array of bytes you could define this helper class: 

class CByteInitializer
{
	int m_count;
public:
	CByteInitializer(int count) : 
			m_count(count) {}
	BYTE* operator()(BYTE* pCurrent) 
	{
		for (int x = 0; x < m_count; x++)
		{
			*pCurrent = 0;
			pCurrent++;
		}
		return pCurrent;
	}
};

 


Here, the operator()() will initialize to zero the first m_count bytes pointed to by pCurrent. It is used as follows: 

// one meg buffer
CVirtualBuffer<BYTE> byteArray(1024 * 1024);
// initialize the first 10K to zero
CByteInitializer init(10 * 1024);
byteArray.Write(0);
byteArray.WriteBulk(init);

 


Why call to Write() before WriteBulk()? Because of the way Except() works: when the code in CByteInitializer first tries to write to the buffer, only the first page has been committed. When a write is attempted to the second page, the exception is caught by WriteBulk() and is passed to Except(), which tries to determine the number of items written to the buffer. However, only CByteInitializer::operator()() knows this; the internal members of CVirtualBuffer<> will think no items have been written, so it will commit no pages and return back to the code that threw the exception, which will try to do the write again and we'll be in an eternal loop. Writing a single item to the buffer means that CVirtualBuffer<> knows there is data in the buffer, so Except() will commit pages. I consider this a bug. 

The final method is the conversion to BSTR. I find this a little odd, because when you call this method you are making another copy of the data-not a good idea if the buffer holds huge amounts of data. You could argue that this is necessary to make an inter-process or an inter-machine COM call, but I would question whether this is the best way. If you are making an inter-process call, why not share the data via a memory-mapped file; if the call is inter-machine, should you really be passing huge amounts of data like this? 

 
Summary  


The ATL container classes provide you with simple, tight code to contain data. They do not provide all the functionality that you may find in STL or MFC, and they may not be as efficient, but they do the job and the code is small. 

 
Richard Grimes is the author of Professional DCOM Programming and Professional ATL COM Programming. His latest book for Wrox Press is called ATL COM Programmer's Reference and covers ATL 3.0. He can be contacted at atl.dev@grimes.demon.co.uk.  



c0Title: CRC-32 without using a lookup table
c1Code:
28 October 2006: We recently needed a version of CRC-32 to use in a C program that didn't use a lookup table. We couldn't find a version on the Net, so here is our version in C. This is the same standard CRC-32 from above which gives CRC("123456789")= 0xCBF43926. There's probably a neat trick to eliminate the use of temp. 
unsigned long crc_octets(const unsigned char *octets, int len)
{
  unsigned long crc = 0xFFFFFFFF;
  unsigned long temp;
  int j;

  while (len--) 
  {
    temp = (unsigned long)((crc & 0xFF) ^ *octets++);
    for (j = 0; j < 8; j++) 
    {
      if (temp & 0x1)
        temp = (temp >> 1) ^ 0xEDB88320;
      else
        temp >>= 1;
    }
    crc = (crc >> 8) ^ temp;
  }
  return crc ^ 0xFFFFFFFF;
}


c0Title: Create and Destroy Objects Properly
c1Code:
http://www.devx.com/premier/mgznarch/vcdj/2000/09sep00/ds0009/ds0009.asp

Use special class functions to ensure solid implementation of your object-oriented design. 

by David Steinhoff 


   The great aha!s of object-oriented programming usually occur during the conceptual and high-level design stages for a new piece of software. Although hardly heroic, most programmers recognize that the detailed design and implementation that follows is the most satisfying part of the process. Only after programmers turn the OOD cloud graphs into hard code can they see if the design works, or if it even makes sense. For any nontrivial program, however, it can be virtually impossible to know how good the design is when the classes it specifies have been implemented badly. Poor execution at this step means the code might not work, it won't be maintainable or extensible, or it can't be reused (gasp!). Properly using the C++ classes' special functions that create and destroy objects can help ensure your object-oriented programming successfully crosses the bridge from design to implementation. I'll show you how to use these special functions. 
What you need:
Visual C++ 6.0  
 
I'll cover these class components: the default and copy constructors, the copy assignment operator, and the destructor. No single rule applies to all class definitions�classes are used in far too many ways. I won't address any coding errors detected by the compiler, because I want to look at less obvious problems you won't be warned about. I also won't cover some important elements of class design, namely initializing template objects and handling exceptions during construction and destruction. These broad topics deserve separate consideration. 

Start by reviewing the rules for constructing objects. Remember that the constructor initializes an object as soonas it comes into scope. The class designer defines some number of overloaded constructors, where each constructor contains a different argument list. Object construction must handle all data members in the class, whether they're part of the local class or inherited from base classes. 

The mechanical rules for initialization are straightforward. The first rule: The compiler calls the constructors for any base classes before calling the constructor for the current class. The compiler applies this rule recursively, so that the constructor for a parent class executes before the child class's constructor. Virtual base classes and multiple inheritance are more complicated and beyond the scope of this article. 

The second rule: The compiler calls the constructor for the current class. It initializes the class's data members in the order that the member declarations appear in the class definition. Once the data member initialization finishes, the constructor function body executes. 

These two rules underlie three common, but subtle, programming problems. Even the most apparently simple constructors can have well-known errors the compiler won't catch. First, consider this class definition: 

class X {
public:
   X() : _c( 1 ), _b( _c * 2 ), _a( 
               _b * 2 ) {}
   private:
   int _a;
   int _b;
   int _c;
}; // X
You might think the values of the class members after initialization should be _c=1, _b=2, and _a=4. However, the second rule dictates that the compiler will initialize _a, then _b, then _c. So, when the _b initializer runs, the value of _c is still undefined. The same is true for the _a initializer with respect to _b. This common error results from a needless confusion. To reduce the likelihood that this confusion will trip you up, you should show the initializer list members in the same order you declare them in the class. 
This illustrates the second problem: 

   class X {
   public:
      X()
      { _sp = "Hello"; }
   private:
      string _sp;
   }; // X
The compiler initializes every class member before calling the constructor function, so this example needlessly initializes the string object to an empty state, then copies in the desired contents. The net effect: The code calls both the string class default constructor and assignment operator functions, when you could have achieved the desired result more efficiently with this constructor definition: 
   X() : _sp( "Hello" ) {}
This example has a minimal impact on the program's performance, but you can easily see how an object more complex than a string could allocate memory or other resources in its default constructor and replace the resources in the assignment function. Also, by taking advantage of constructor vs. assignment function semantics (that is, by using member initialization instead of assignment), the program generates fewer unnecessary temporary objects. You should initialize rather than assign during construction, except in special cases. 
The third problem is specific to class hierarchies where the constructor calls a virtual function. This sample code declares a virtual member function in the base class, which the derived class overrides: 

   class X {
   public:
      X() { Doit( ); }
      virtual void Doit( ) {
         cout << "X::Doit\n" }
   }; // X

   class Y : public X {
   public:
      void Doit( ) {
         cout << "Y::Doit\n" }
   }; // Y
You might expect the code to call X::Doit() if you construct an object of type X, and to call Y::Doit() if you construct a Y. Unfortunately, the code never calls Y::Doit(). According to the first rule, the compiler first calls the X() constructor, and uses the X class's vtable to resolve the address of the virtual function, Doit(). During the time that the X::X() function is executing, the object is an X. So, the only virtual function Doit() known to the object is X::Doit(), which the X vtable points to. The compiler updates the vtable to point to the virtual functions of class Y before it calls the Y() constructor (see Figure 1). If you must call a virtual function from a constructor, at least comment the call to make the virtual status clear. 
   
Figure 1. Call a Virtual Function From a Constructor. Click here.

 
Create Objects With Special Constructors 
The default constructor and the copy constructor are special functions, because for many classes the compiler creates them for you if you don't create them yourself. This usually works just fine because most classes need both of these constructors, but their function is often simple enough that the program requires only the default behavior supplied by the compiler. The definition of a default constructor is a constructor you can call with no arguments. A constructor that supplies defaults for all its arguments is still a default constructor. These are therefore both legal default constructor declarations for some class X: 

   X();
   X( int i = 1 );
Naturally, only one of these constructors can appear in a given class definition, because the overloading resolution mechanism in the compiler cannot differentiate between them. Unless you need to explicitly initialize system resources in the default constructor, you probably don't need to declare the first form; remember that the compiler generates it for you. However, letting the compiler supply the default constructor sometimes has undesirable side effects. The compiler always declares the implicit default constructor with public access. However, you might want to keep it private or protected, in which case you must explicitly declare it that way. Consider a class that has no meaningful initialization by default construction, but that you can read from an IO stream. You could handle this by declaring the istream operator>> function as a friend, and that function could create an empty object, which it then fills from the stream. 
Another reason to declare the default constructor yourself seems paradoxical�because you don't want a default constructor at all! What if you don't ever want the program to create an instance of a class using the default constructor? You can address this straightforwardly by declaring the default constructor private and by not supplying the definition anywhere in your code. The linker will catch any use of the default constructor with an error advising you that the default constructor function is undefined. The linker will even catch a friend function, which has access to private functions. You can apply this technique to the other special functions described in this article. 

Defining the default constructor using one or more default arguments is useful mainly when you want to initialize the object's contents to known values. C++ doesn't allow you to create an array of objects unless the object's class has a default constructor. This technique allows you to create arrays and apply special initial values. Either a function call or a constant value can supply a default argument's value, so objects initialized by a default constructor can still have unique contents: 

   X( Registry reg = 
         GetNewSerialNum() );
In general, constructors have problems that result from subtle aspects of the C++ language definition. First, constructors are not regular functions. They have no return type (not even void), they have no actual name, you can't call them directly, and you can't take their addresses. Given a class X with a default constructor, provided either implicitly or explicitly, this statement is legal: 
   &X::X();
but it doesn't yield the constructor function's address, as you might expect. Instead, this statement creates an unnamed temporary object (which it initializes using the default constructor) and returns the address of the temporary object. It might seem desirable to acquire and store the constructor function's address for some parameterized use elsewhere, but that is simply not allowed. This also yields a surprising and usually disappointing result: 
   X x1();
The unwary programmer thinks he has created an object of class X using the default constructor. Unfortunately, the C++ language doesn't allow you to declare an object using the default constructor using an empty argument list. You must instead program it this way: 
   X x1;
This is the only exception to the C++ rule that a function must be called or referred to with an empty argument list when the function takes no arguments. The non-obvious implication: The first form is a perfectly legal declaration of a function named x1 that takes no arguments and returns an object of type X. You'll want to remember this one when you apply for a job as a C++ programmer and you are asked to take "a little test on the language." 
C++ provides the other special constructor so you can initialize an object from another object of the same type (that is, to copy it). The copy constructor can take two forms for a given class X (ignoring the deprecated volatile specifier option), both of which require the first argument to be a reference: 

   X( const X& other );
   X( X& other );
You can create both copy constructor functions for a given class, and the compiler's overloading resolution mechanism selects the appropriate one. VC++ 6.0 won't allow you to create both for the same class because of a bug. You can't default the first class argument, but subsequent arguments can have defaults. If you supply a default for the first argument, or if nondefaulted arguments follow, the constructor is legal, but it isn't a copy constructor. These examples illustrate constructors for class X that do and don't follow the rules: 
   X( const X& other = X() );  
   // This declares a default ctor
   X( const X other );  
   // Illegal; other is not a 
   // reference
   X( const X& other, int i = 1 );  
   // OK
   X( const X& other, int i );  
   // Legal ctor, but not a copy ctor
The compiler creates an implicit copy constructor for a class that doesn't declare one explicitly, and it chooses between the const or non-const forms based on the class's context. If all base classes and their members have copy constructors of the const& form, this class gets one that follows that form. The compiler supplies a non-const& definition in all other cases. 
The most common situations where the compiler calls the copy constructor in your program is upon entry and exit from functions. Here's an example of both: 

   // Ex 1
   void Foo( const X xarg ) {
      // ...
   }
   X x1;
   Foo( x1 );

   // Ex 2
   X Bar( ) {
      X locX;
      // Modify locX...
      return locX;
   }
   X x2 = Bar( );
In the first example, the code calls the function Foo() with an object of type X. Foo() doesn't declare the argument either as a reference or a const, so the compiler generates code to create a new X local to Foo() using the copy constructor. The compiler then pops the object from the stack (destructs it) upon its return from Foo(). 
In the second example, the function Bar() creates a local X object and "returns it." Actually, the local object isn't returned. That object goes out of scope when the function Bar() exits, but the runtime creates a copy using the copy constructor and returns the copy. Then object x2 initializes using the copy constructor, and finally the returned object goes away. A single call to Bar() invokes three constructor calls and two destructor calls in this example. These examples define the functions Foo() and Bar() inefficiently, because they do a poor job of managing local and temporary objects. You should write them this way instead: 

   void Foo( const X& xarg ) {
      // ...
   }
   X x1;
   Foo( x1 );
   X& Bar( X& xarg = X( ) ) {
      // Modify xarg...
      return xarg;
   }
   X x2 = Bar( );
Now, a call to Foo() doesn't destroy or create any object. The call to Bar() creates two objects and destroys one, but a smart compiler might do even better. 
The second C++ special copy function, the copy assignment operator, is perhaps the most misprogrammed function in the C++ language. Where the copy constructor copies an existing object into a newly created one, the copy assignment function copies from one existing object into another existing object. Like the other functions in this article, the compiler creates the copy constructor if you don't create it yourself. The rules governing copy assignment are more complex than for the other constructors discussed so far. 

You should distinguish carefully between the two copy functions. This code illustrates their usage: 

   X x0;
   X x1( x0 );	// (1)
   X x2 = x1;	// (2)
   x2 = x1;	// (3)
Statement (1) calls the copy constructor to initialize x1. Statement (3) calls the copy assignment function, because x2 already exists. But what about statement (2)? You might expect it to call the copy assignment function, given the use of the assignment operator, but the compiler recognizes that this statement is initializing x2 and calls the copy constructor instead. Beginning C++ programmers might find it hard to distinguish between the two copy functions; unfortunately, the language syntax doesn't make the distinction clear. They might be similar in purpose, but they have profoundly different behavior. Now you'll look at some of the copy assignment function's unique aspects. 
The copy assignment function is a binary operator function of the form a = b. The operator function declares the right-hand object, b, as one of these forms: X, X&, or const X& (again ignoring volatile). Remember you can also define additional assignment operator functions that take any other object type. The semantics of the implicit copy assignment function and the copy constructor are similar, in that the runtime calls the base class copy assignment functions and the member assignment functions in the same recursive order, and the implicit assignment function is public. However, the compiler doesn't supply this default behavior if you create your own copy assignment function, like this: 

   X & operator=( const X& rhs );
Here, none of the automatic behavior takes place: The compiler does not call the base class and data member copy assignment functions. You have assumed the entire burden of copying the object yourself. You must either copy all the members of the current class and base classes, or else you must call the copy assignment function of the base class: 
   // Assume class X is derived from 
   // class Y
   X & operator=( const X& rhs ) {
      Y::operator=( rhs );
      // Copy X members over...
      return *this;
   }

You also must make sure you protect against any harm that might result from copying an object onto itself, as might happen if the object contains a pointer member: 
   // Assume class X has a pointer 
   // to Ptype member
   X & operator=( const X& rhs ) {
      delete pmem;   // (1)
      pmem = new Ptype( *rhs.pmem );
      // ...
   }
If the assignment statement looks like: 
   x1 = x1;
the program will blow up because rhs.pmem is this->pmem, but the statement marked (1) destroys rhs.pmem before copying it. You can avoid this error by testing to see if both objects are the same, and short-circuiting the copy operation if they are: 
   // Assume class X is derived from 
   // class Y
   X & operator=( const X& rhs ) {
      if ( rhs == *this )
         return *this;
      // ... else copy
   }
What's in a Destructor? 
The destructor is the final special function I want to address. As with the others, the compiler creates a destructor if you don't do it yourself. You can't overload this function, and it never takes arguments, even default ones. It has characteristics symmetric to constructors, as you would expect. The compiler calls the destructor for the current class members in the reverse order they were declared, after which the compiler calls the destructors for the base classes, also in reverse order. Also, similar to constructors, the destructor doesn't have a name, and your program can't take its address. The correct form of the destructor declaration for class X is: 
   ~X( );
However, destructors differ from constructors in two ways. You can call a destructor directly, as in: 
   X x1;
   x1.~X( );
Once you call the destructor, x1 no longer exists, even though its name is still in scope. The results of referring to x1 subsequently are undefined. Programs seldom call the destructor directly; you would use this technique only in unusual environments, such as volatile or shared-memory computers where the program directly manages object lifetimes. The construction complement to this technique is creating such objects using the new operator placement syntax. 
Another characteristic worth mentioning: You can declare the destructor to be a virtual function. You would most commonly do this when you expect a pointer to an object to be passed to a function that takes a pointer to a base class of the object. If the function deletes the pointer object, the compiler won't call the actual destructor of the derived class. This code demonstrates the problem: 

Class X {
public:
   ~X( ) { cout << "In X::~X\n"; }
}

class Y : public X {
public:
   ~Y( ) { cout << "In Y::~Y\n"; }
}
// ...
void Foo( X* xp ) {
	delete xp;
}
// ...
X * xptr = new X;
Y * yptr = new Y;
Foo( xptr );
Foo( yptr );
In this example, the compiler never calls Y::~Y. You can easily fix this by changing the declaration of X::~X to: 
	virtual ~X( ) 
	   { cout << "In X::~X\n"; }
The compiler won't make the implicit destructor virtual, so you must declare it in order to make it virtual. 
The special functions in C++ can quietly change a program's semantics. Often called "public defender" functions by punsters, these functions are by default public, and they do defend against incomplete class definitions. But the real reason for their nickname is they take after the legal guideline that "...if you do not create a copy constructor (etc.), one will be created for you." The default implicit behavior of all these functions is just right for most classes, but when you create a class that has additional creation, copying, and destruction semantics, you take on some burdens that you perhaps never knew existed. 


David Steinhoff is the vice president for software development at Clareos Inc., a startup company in Ann Arbor, Mich., specializing in high-performance database analysis. He has worked with C++ professionally for more than 12 years and has taught the language to developers at many companies. Reach him at welder@ic.net
 


c0Title: Create Conditional Breakpoints
c1Code:
VC++ 6.0 | 

Tired of setting and resetting breakpoints manually on Intel x86 architectures, as well as DOS and Windows platforms? Create fully conditional breakpoints: 

if (breakpointCondition)
{
	__asm {int 0x03; }
}
Not only is this a proper breakpoint, but it's also smaller and better than Win32's DebugBreak() API call�you might have to step into DebugBreak(), I've found. When DebugBreak() is called, the debugger breaks in the Win32 API library itself. The DebugBreak() call looks like this: 
int 3
ret
After the breakpoint has been reached, you must step over the RET statement before you can return to your code. With my approach, the debugger breaks within the code where you placed the __asm int 3. 

Because this approach involves calling the hardware debugger interrupt, you can use this code in DOS, Win32, ATL, and MFC applications. 

�Scott Tunstall 


c0Title: Create Windows Installer packages
c1Code:
June 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/tr0600/tr0600_02.asp
  Tool   Review
  

  Q u i c k F a c t s 
Visual Studio Installer 1.0 
Microsoft Corp. 
Phone: 800-621-7930 
Web: www.microsoft.com 
Price: Free to licensed users of any Professional or Enterprise edition of a Visual Studio product or as part of the MSDN Subscription CD 
Quick Facts: Create simple Windows Installer-compliant installations in the Visual Studio environment. 
Pros: Covers standard types of setups. Quick package creation after learning curve. Visual Studio integration. 
Cons: Steep learning curve. No GUI presentation of dialogs. Limited setup options. 
--------------------------------------------------------------------------------
 
Additional Reviews 
TegoWeb Express Standard Edition 6.7.19 
More Product Reviews 
 


by Brian Noyes

W hy should you trust version 1.0 of any software? If you want to ensure your installation packages are Windows 2000-compliant (and backward-compatible with Windows 95/98/NT, of course), why not go with the product developed by the people who write the standard and the operating systems? Besides, it's free if you own a Professional or Enterprise edition of a Visual Studio product. 
Microsoft Visual Studio Installer is an installer-package creation tool that integrates with Visual Studio. Its main focus is to create installer packages that work with the Windows Installer technology. If you're unfamiliar with Windows Installer, read about it in MSDN (http://msdn.microsoft.com/vstudio/downloads/vsi/ordering.asp). 

Getting started with the Installer presents a steep learning curve, but once you figure out the basics, putting together an installation package for your applications is fairly quick and easy. 

VS Installer starts with a project wizard that lets you create an empty Installer project, an empty Merge Module project, or a Visual Basic Installer package. VS Installer uses Merge Module packages to contain shared components that more than one installation package will use, such as the MFC and C run-time libraries. 

   
Figure 1  
The Project Explorer window, which provides the top-level interface to your project, shows a treeview with nodes for the target machine and project files. The real action centers around the Target Platform node, which contains nodes for the file system, user interface, Registry, and associations. By double-clicking on each of these, you get a specialized window, which displays items relevant to the associated node and context menus that help you perform the relevant tasks for that node. You can then set properties for selected items in the Properties window, and check out the Task List window for hints of compilation errors or configuration options you should change. 

Not an End-All, Beat-All Installer Tool 
The program doesn't give you a lot of help with some of the more common tasks in an installation package, such as creating menu items. You also have no way of previewing the dialogs the user will see, other than compiling the package and running it to see how it looks. You can find Help documentation through the Start menu shortcut installed under the VS Installer menu, but the language of the help files has a little too much marketing hype and not enough tutorial assistance. 

Other Restrictions 
The other big limitation: You're restricted to using only the dialogs, steps, and options predefined in VS Installer, which are limited to just the basics. So you can't create your own custom steps, and you can't perform other special tasks, such as running a program at the beginning or end of the installation. 

But despite these limitations, and as long as you're just trying to create a straightforward Windows installer package without a lot of bells and whistles, Visual Studio Installer is a good tool that lets you do this quickly. And you can feel confident that the package is compatible with Windows 95, 98, NT, and 2000. 


Brian Noyes is an independent software consultant with DomeWorks Software (http://domeworks.com). He is an MCSD with nine years of software development, project management, and test and evaluation experience. He is a technical reviewer and occasional author for Visual C++ Developers Journal. You can reach him at bnoyes@domeworks.com. 

TegoWeb Express Standard Edition 6.7.19
 


c0Title: Create Your Own ATL Object Wizard
c1Code:
June 2000
 

    ATL Advantage 

http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/aa0600/aa0600.asp
Write an ATL Object Wizard to customize the objects you use most often. 

by Richard Grimes 


   The ATL Object Wizard generates code and adds the source files to your project. This ATL Object Wizard-generated code is based on "template" files you manipulate through a script that uses information you add through the Object Wizard's pages. Creating an ATL Object Wizard of your own can save you time and effort. For example, if you're working on a project in which you regularly turn out components that share features (for example, special error handling that logs errors to the NT Event Log), you can save yourself considerable time and avoid errors in common code by creating an Object Wizard for the common portions of the component code. 
What you need:
Visual C++ 5.0 or 6.0  
 
The good news: This process is relatively simple. In this article, I'll outline the process and discuss the files you need to create, as well as how to install them. First you need to understand how the Object Wizard works, then learn how to get the information from dialogs and use it to generate code. 

Start the Object Wizard by selecting New ATL Object from the Insert menu while in an open project workspace. If the current project is an ATL or MFC project, you'll see a dialog like the one shown in Figure 1. It might seem surprising that you can add an ATL class to an MFC project because you might be more familiar with adding MFC support to an ATL project. However, the converse is possible because the Object Wizard determines whether the current project is an MFC project, and if so, it runs a script to add code into the project to support ATL. 

   
Figure 1. Use this ATL Object Wizard dialog... Click here.

 
On the left side of the dialog are the categories of objects you can create, and on the right side are the objects for the selected category. The categories group the types of objects to make it easier to locate the particular wizard you want. The individual object wizards allow you to add new ActiveX controls and COM objects to your project, but they're not confined to just COM code. In fact, you can add a dialog class to your project that doesn't have to use COM at all. 

When you select the Next button after highlighting a particular type of object, the Object Wizard locates a script file for the object type and runs it. This script might create a tabbed dialog similar to the one shown in Figure 2, which shows the Attributes page for the Simple Object type. You can enter values into the tabs' controls to provide information the script uses to generate the code for the selected object type from "template" files. (Note that by "template" files I don't necessarily mean C++ templates�I'm using the word nearer to its actual meaning. That is, these files have code the Object Wizard script will use as a basis for the code it generates. This code can consist of C++ templates, of course, but it doesn't have to!) 

   
Figure 2.When you select an object type... Click here.

 
In Figure 2, for example, the script for a simple object uses the Threading Model attribute to determine whether the generated ATL class will use CComSingleThreadModel or CComMultiThreadModel to control access to its data members. 

The Object Wizard gets information about the objects you can add to your project by looking into this registry key: 



HKEY_LOCAL_MACHINE\SOFTWARE\ Microsoft\DevStudio\6.0\ATLWizard

Under this key, you'll find more keys named with a GUID. These GUIDs aren't significant; their only purpose is to guarantee that each key has a unique name. Each key has four named values (category, control, icon, and name). 

The first value is the category of the object type (the left pane in Figure 1). If that category already has object types, the Object Wizard adds a new type to them; otherwise, it creates a new category. The Object Wizard adds the type into the right pane and displays the name given by the Name value with the icon specified by the Icon value. When you select the object type and click on the Next button, the script indicated by the Control value is run. These two files (the script and icon), as well as any files used by the script, are held in a single folder that resides in the Visual Studio folder (typically C:\Program Files\Microsoft Visual Studio): 



\Common\MSDev98\Template\ATL

The Visual Studio folder has three types of files: the scripts (CTL), icons (ICO), and "template" files used by the scripting code. For an example of a "template" file, check out PropPage.cpp, which is used to generate the CPP file for a property page. As you can see, the code isn't real C++�note the strange directives in square brackets. These are examples of the custom scripting code that the Object Wizard uses. These lines in PropPage.ctl (edited for clarity) use the PropPage.cpp file: 



[!AddStringToSymbol(CPPTemplate,
   GalleryPath, "proppage.cpp")]

[!target(CPPName)]
[!include(CPPTemplate)]
[!target()]

[!AddFileToProject(CPPName)]

The Object Wizard maintains a symbol map that has symbol-string pairs. Most of the commands in the Object Wizard scripting language take symbols as their parameters rather than strings, so before you can use these commands, you must create symbols for the strings. You can do this in several ways; I've shown one way in the preceding code. This code adds the full path to the "proppage.cpp" file as the symbol CPPTemplate, assuming this file is in the folder that contains the CTL and template files. The Object Wizard has a standard symbol called GalleryPath that contains the path to this folder. [!AddStringToSymbol()] prefixes the string in GalleryPath to the string "proppage.cpp" and places the entire path in the CPPTemplate symbol. 

After creating this new symbol, the code generates a new file based on the code in the "proppage.cpp" template files. The new file is generated by a call to the [!target()] command with a symbol named CPPName (which has been set by a dialog; I'll discuss this in a moment). This call to the [!target()] command creates the new file with the name given in CPPName and directs all output to the new file until the second [!target()] line is called. Because this second call has no filename, it closes whichever file is attached to the output. You can temporarily prevent text from going to the output file by using [!OutputOff] and resume the text by using [!OutputOn]. 

The [!include()] line processes the file referenced by the symbol passed as a parameter (in this case, CPPTemplate) and passes the processed information to the output stream. This file also contains scripting code based on other symbols. In general, symbols come from two sources: first, the PropPage.ctl script (I've omitted these lines in the preceding code snippet); second, any dialogs that the script shows. 

Now try adding your own Object Wizard script to test how the scripting language works. To do this, type this code into a text file called install.reg, save the file, then double-click on it in Explorer: 



REGEDIT4

[HKEY_LOCAL_MACHINE \SOFTWARE\
Microsoft\DevStudio\6.0\ATLWizard\
{E1DACC30-E9E2-11d3-8A82-00104BDC35E0}]
"Category"="Test Objects"
"Control"="Test.ctl"
"Icon"="Test.ico"
"Name"="Test Script"

(Watch out for line splitting; the name of the key should be on one line.) Now add a suitable icon file and an empty text file called Test.ctl to the template directory (download the code). Type this text into the CTL file: 



[!set(FILE_NAME, "Test.txt")]
[!target(FILE_NAME)]
The project is saved in [!ProjectDirectory]
[!target()]
"Name"="Test Script"

Send Text to a File
The first line creates a new symbol called FILE_NAME and gives it the value "Test.txt". When the Object Wizard creates this file in the second line, it will use the project directory because the code doesn't include a full path. 

To test this example, create a new ATL project and start the Object Wizard. You should see a new category called "Test Objects" with a single item called "Test Script." Click on the Next button; nothing seems to happen. However, if you examine the project directory, you'll find a new file called Test.txt, as expected. This file contains a string that identifies the project directory. You get this text because any text not in square brackets is sent to the output stream. If you include the name of a symbol in the [!] directive, the value of that symbol is also sent to the output stream. 

Now add this line to the end of the CTL file: 



[!AddFileToProject(FILE_NAME)]

When you run the script, you should notice two things. First, the Test.txt file is added to the project (look in the project Workspace using FileView). Second, notice that running the script a second time appends the string to the end of the file. In other words, [!target()] opens and appends text to a file if it already exists. If this is not the behavior you want, add this line after the [!set()] line to delete the existing file: 



[!DeleteFile(FILE_NAME)]

As you can see in the previous example, you can use [!set()] to add a symbol to the map; you can use a corresponding command called [!RemoveSymbol()] to remove a symbol. You can also determine whether a symbol has been set using the commands [!if()], [!else], and [!endif] and passing the name of the symbol to the [!if()] command: 



[!set(FILE_NAME, "Test.txt")]
[!if(FILE_NAME)]
FILE_NAME has been set to [!FILE_NAME]
[!else]
This line should never occur
[!endif]

In addition, you can check if a symbol has a specific value using [!if=()]�as in [!if=(FILE_NAME, "file.cpp")]�and [!if!=()]. However, note that this command performs only string comparisons. If you want to set a Boolean, you have several choices. You either use the existence of the symbol as your Boolean true (and use [!if()] to determine whether the symbol exists), or you test for a value in the symbol. Object Wizard scripts use two conventions here: Either the symbol has the string "TRUE" or "FALSE," or it has "1" or "0." You should choose one of these conventions and stick to it. 

Create Your Own Dialogs
The dialogs that the Object Wizard shows are actually property page objects, and you can use ATL to create your own. As with other property pages, the page is passed an array of IUnknown pointers that correspond to the objects the property page will act on. In ATL, the IPropertyPageImpl<> template gives you access to this array through a data member called m_ppUnk. The first member in this array is the symbol map that has the interface shown here: 



[
 object,
 uuid(C6D58201-1FA3-11D0-BF1E-0000E8D0D146),
 pointer_default(unique)
]
interface ISymbolMap : IUnknown
{
   HRESULT Set([in] LPCOLESTR strSymbol, 
      [in] LPCOLESTR strValue);
   HRESULT Get([in] LPCOLESTR strSymbol, 
      [out, retval] BSTR* pstrValue);
   HRESULT Clear();
   HRESULT SetStatus(const CLSID* pclsid,
      BOOL bEnableOK);
};

To access the symbol map, simply query m_ppUnk[0] for this interface, usually in your property page's handler for WM_INITDIALOG. 

The methods in ISymbolMap are self-explanatory; you can obtain and set symbols using Get() and Set(), and clear the map using Clear(). By default, the property sheet dialog's OK button is disabled. To enable the OK button, your property page calls SetStatus(), passing its CLSID and a BOOL to indicate whether the property sheet's OK button should be enabled. This is useful when your property page validates some of the values in its controls. 

Every property page should implement IPropertyPage::Apply(), which is called when a property dialog's OK button is clicked on. You can use this method to set any symbols to the values in your property page's controls. 

Once you've created and registered the property page, you need to call it in your script. To do this, make sure the property page has a ProgID of the format name.name. The Object Wizard has several dialogs, of which I'll dwell on only two: Names98.Names98 and ObjDlg98.ObjDlg98. These are the familiar Names and Attributes pages that you get with the Simple Object type. To create a dialog with these pages, pass the name of each page to [!Dialog()]: 



[!Dialog("Names98", "ObjDlg98")]

This command can take up to nine parameters, so you can have up to nine pages. If you want, you can disable some of the controls on these pages. To do so, set a symbol associated with the page (ComponentType for Names98; Attributes for ObjDlg98) to a string that represents a bit pattern. I've included the bit patterns you can set for the ObjDlg98 page (see Table 1). For example, if you want to show the Attributes page, but disable the Free Threaded Marshaler checkbox (always a good idea) and the Custom Interface radio button, you can use this code in the script: 



[!set(Attributes, "00000100001")]
[!Dialog("Names98", "ObjDlg98")]
[!if=(ErrorInfoEnabled, "TRUE")
The user requested support for ISupportErrorInfo
[!endif]

When the dialog closes, it sets symbols with values you enter into the controls (see Table 2 for the Attributes page symbols). See Links and Resources for the bit pattern symbols and the symbols set by the other standard pages. 

Why write your own Object Wizard object types? Several reasons. First, the scripts supplied with Visual C++ 6.0 contains some bugs that you can fix by writing your own versions. For example, the Links box lists the source code of my latest book, where I provide a fix to an odd anomaly. The MS Transaction Server Component type does not allow you to generate error objects in the component and suffers an inconsistency in which the component has a ThreadingModel of Both, but the ATL class derives from CComObjectRootEx<CComSingleThreadModel>. Although this inconsistency doesn't affect MTS, it does mean your component could be thread-unsafe when used as a COM+ component. 

You might also decide you want to provide your own object type, perhaps an object that supports a specific interface. If this is the case, you can write your own Object Wizard script and customize it by writing your own Object Wizard property pages. 


Richard Grimes is the author of Professional ATL COM Programming and Beginning ATL 3 COM Programming, which both cover ATL 3.0 (available from Wrox Press). Richard's latest book, Visual C++ 6 MTS Programming, was published by Wrox Press last fall. Contact him at atl.dev@grimes.demon.co.uk
 


c0Title: Debug Multithreaded Code
c1Code:
April 2000
 

    Ask the VC++ Pro 

http://www.devx.com/premier/mgznarch/vcdj/2000/04apr00/ap0400/ap0400.asp
by Davide Marcato 


     Q.The Case of the Crashing Multithreaded Server 
I'm trying to build a simple Windows NT server application in Visual C++ that executes externally requested database operations. The requests arrive asynchronously by a proprietary InterProcess Communication (IPC) protocol. Because the application doesn't need to handle big traffic, for simplicity's sake I decided to stick to a single-thread program. 
I broker operation requests on my archives. The process's main thread listens on an out- of-process connection, and whenever somebody rings in, the process services the connection, then goes back to its idle state. The database operations primarily involve database queries on a data archive through ADO. Alas, my code doesn't work�my server crashes a few seconds after the last operation! The behavior is regular, but inconsistent in time and duration. Please help! I'm working with Visual C++ 6.0 SP3, ADO 2.1, Windows 2000 Server, and Access/SQL Server as the back-end DBMS. 

What you need:
Visual C++ 6.0
ATL 3.0
Windows 2000
 
 
A. If you're a UI programmer, developing multithreaded code for server-side software is a delicate and complicated task. You'll probably have trouble debugging this type of code because it's hard to predict a multithreaded system's state at any point in time. To deal with an unexpected bug, first break down the whole into smaller parts, thereby surrounding the guilty code in a minimal, stripped-down program. Look at this source file (Listing 1) , which I extracted from your sample application. It still manifests your bug, but highlights the crucial passages causing the trouble. 

"Wait a minute!" you say�this code is single-threaded, so why do I rant about multithreaded debugging? By walking you through the code, I answer this question and demonstrate how to debug multithreaded applications. 

This Visual C++ program first initializes the COM subsystem for the current thread by calling ::CoInitialize(NULL), which creates the main COM single-threaded apartment. Then, in the Test() method, the program executes a SQL SELECT query against a database, opening both a Connection object and a Recordset object as part of the operations. After the Test() function returns, it cleans up the COM elements through ::CoUninitialize(), and waits for keyboard input�thus replicating the same no-operation, idle state the reader's code goes through while awaiting a new request. 

The code in Listing 1 looks perfect, both syntactically and semantically, and Visual C++ compiles it flawlessly. Once the program runs, it effectively executes the query, but what happens next depends on which operating system you're using. With Windows NT 4.0, including Service Packs 3, 4, 5, and 6, the execution pauses indefinitely at the getchar() line; with Windows 2000 RC2, the program crashes. 

The program crashes in both the debug and release modes with Windows 2000 RC2. In the release mode, the process for the application that has just run disappears from the task list; while in the debug mode, Visual C++'s debug window fills with hundreds of Access Violation error messages just before the program crashes. Given I've restricted the field of operations, either the getchar() function call or another piece of code running simultaneously must cause these memory errors. However, implementing a common run time library (RTL) function probably wouldn't unleash such a destructive bug, so I suspect someone is executing hidden code in the process. 

In fact, even though the main thread executes the steps I've outlined precisely, the ADO code the database operations rely on spawns several new threads behind the scenes to carry out the work. There's no detailed documentation to describe what the code does or when those threads are created and terminated. Actually, I'm not sure who exactly creates such threads. Remember that ADO is just a layer over OLE DB, which calls OLE DB drivers to operate diverse data sources and formats. 

Typically in OLE DB, multiple concurrent clients attempt to manipulate parts of a database, so you must improve efficiency by using connection pooling, and you have to guarantee appropriate data locking. Even though Listing 1 doesn't have these auxiliary services, that doesn't mean you don't need them. Also, because all these different libraries and drivers are physically shipped as dynamic link libraries (also known as in-process servers), they end up in the process's memory�so, the new threads run within the process. This is how multithreading problems can suddenly plague an innocent single-threaded application. 

Visual C++ 6.0 IDE's debugging capabilities are a great tool for tracking and inspecting a multithreaded application. In this example, stepping through ADO/OLE DB code at run time isn't convenient because the example doesn't have the libraries' source code. Nevertheless, by using the Debug window, you can learn when a thread is created and destroyed in a debugged process. During the keyboard input loop on Windows NT 4.0 (where the bug doesn't manifest itself), the Debug window listed this sequence of dead threads: 



The thread 0x754 has exited with code 0 (0x0).
The thread 0x16C has exited with code 0 (0x0).
The thread 0x6EC has exited with code 0 (0x0).
The thread 0x55C has exited with code 0 (0x0).
The thread 0x728 has exited with code 0 (0x0).
The thread 0x658 has exited with code 0 (0x0).

(For clarity, I've omitted Debug output reports of DLLs and symbols loaded.) This sums up to six "hidden" threads. After a few seconds (about five on my machine), without any activity on the user's side, the list became: 



The thread 0x754 has exited with code 0 (0x0).
The thread 0x16C has exited with code 0 (0x0).
The thread 0x6EC has exited with code 0 (0x0).
The thread 0x55C has exited with code 0 (0x0).
The thread 0x728 has exited with code 0 (0x0).
The thread 0x658 has exited with code 0 (0x0).
The thread 0x720 has exited with code 0 (0x0).

You'll see seven items, indicating that seven threads have been spawned and then destroyed during the process's lifetime! As you can also see, another thread (thread 0x720) died autonomously after the first group of six. When I replicated this same test on Windows 2000 (I used the same machine and a dual boot, to be consistent), I saw the first batch of six threads die. But after a few seconds, the process crashed, the Debug window still reported only six exited threads, and there were more than 1,100 Access Violation messages. I had the same results when I changed the data source to Access 2000, SQL Server, and ODBC. 

Based on the experimental data I collected, I've concluded that the cleanup code OLE DB executes from the seventh hidden thread is your culprit. Given that your sample code is correct, the bug lies elsewhere. In order to eliminate your bug, you'll need to clean up the COM libraries from the seventh thread. Comment out the call to ::CoUninitialize() from main(); this way, you don't shut down COM for the main thread as soon as you could. 

Consequently, the seventh thread performs its COM cleanup operations flawlessly, then terminates gracefully on all platforms (Windows 2000 included) without producing an error message. Depending on how your application is structured, remember to always place a call to ::CoUninitialize() immediately before the process terminates, but after OLE DB finishes all of its tasks. The bottom line: To avoid this bug, postpone COM's cleanup until it's absolutely necessary to abide by COM rules. 

Step-by-step debugging and an incremental reduction of the area where I thought the erroneous code might lie helped me spot this nasty bug (probably caused by Windows 2000 RC2). I also credit additional empirical analysis and luck in helping me find a simple workaround to shield the code from the problem. 

Davide Marcato is president and founder of Marcato Consulting (www.marcatocons.com), a software development and consulting firm specializing in Windows DNA and Internet enterprise solutions. Davide writes for many magazines, including Visual C++ Developers Journal, Dr. Dobb's Journal, MIND, and COM Developer. Contact him at www.DavideMarcato.com
 


c0Title: Discover Class Designs
c1Code:
May 2000
 

http://www.devx.com/premier/mgznarch/vcdj/2000/05may00/fu0500/fu0500.asp
How you construct a class speaks volumes about how that class should be used. 

by Bill Wagner 


     A few weeks ago, while teaching C++ programming students about class design, I was asked an interesting question. One of the students said that most of them would be assigned to maintaining and extending existing code: How was my teaching going to help them? How could they use this new knowledge to understand the code they would maintain? 
What you need:
Visual C++ 6.0, including 
the C++ Standard Library  
 

While we all hope our predecessors will leave us design documentation that explains the programs we must maintain, this is not always the case. In these situations, you can discover the design by examining the code. In this article, I'll examine two different MFC classes�CString and CView�to illustrate how the existing code should be used. Along the way, I'll point out what different design decisions mean, so you can write classes that more accurately express your intent. 

Constructors and destructors are the first functions I look at when trying to understand a class I need to use or maintain (see Table 1). How the constructors are or are not defined tell you how to use the class and what you need to create an object of that class. The presence or absence of a virtual destructor indicates whether the class can function as a base class. 

The MFC CString class supports both a default constructor and a copy constructor (see Listing 1). These two operations are part of what is called the canonical class form. The canonical class form describes any class that supports the same syntactic usage patterns as a built-in type. Any class that has a default constructor, a copy constructor, an assignment operator, and a destructor supports this form. Because the CString class supports the canonical class form, you can use it in a variety of ways, such as placing CString objects in Standard Template Library (STL) collections and using CStrings as local variables. You can also pass CString objects as function parameters by value, and return them from functions by value. Canonical class forms tell you that the CString class is meant to be a simple data structure you can use throughout your programming tasks. 

The next constructors in Listing 1 indicate what abstraction CString represents. All the other CString constructors take some C language representation of text data. They convert a single character, an array of ANSI characters, or an array of Unicode characters into a CString object. These constructors indicate that any of these primitive C language structures can be "promoted" to a CString, meaning that you can use a CString in place of the C language strings. 

Finally, CString's destructor is not a virtual function. This indicates the designer did not intend CString to be used as a base class or polymorphically. If a CString derived class were destroyed through a pointer to a CString object, the derived class destructor would not be called. 

By contrast, examine the constructors and destructors for CView: 


// Constructors
protected:
   CView();
public:
   virtual ~CView();

CView has a default constructor, but it is protected. This implies one of two possibilities: CView is an abstract base class, or you create CView objects through a factory function. The destructor is a virtual function, so you should use this class as a base class. 

Default constructors indicate your class is used as concrete class. A concrete class is a simple datatype that stands on its own. Think of your own use of CString. You create and use CStrings whenever you need to manipulate character data. You can create CStrings on the stack, on the heap, and in collections, and manipulate them through function returns. 

Conversion constructors show what datatype your class represents. In the case of CString, the constructors show that CString represents character data. That character data can be either ASCII or Unicode data. 

The lack of public constructors indicates your class cannot be used except in relation to other classes. Think of all your CView derived classes. You can use CView derived classes only with a CDocument derived class. The MFC framework creates CView derived objects, using the CreateObject() factory function. Now that you understand what the constructors tell you about your classes, you can look for pure virtual functions. 

Search for Pure Virtual Functions
Pure virtual functions indicate the class is an abstract base class. CString doesn't have any pure virtual functions. CView has one pure virtual function, OnDraw(), whose purpose is to draw the view to the window. You must define the OnDraw() function in each derived class. 

If you intend to use your class only as a base class, make sure it includes at least one pure virtual function. In practice, you'll probably have at least one function where you can't implement the behavior for all derived classes. If you can't find any functions that make good candidates for pure virtual functions, you can always make the destructor a pure virtual function. This is fairly common, but it comes with a price: Every derived class must define and implement a destructor. 

You should also look for impure virtual functions. CString has no virtual functions at all, reinforcing the idea that CString is not intended as a base class. On the other hand, CView has many virtual functions, indicating the class designer intended CView to be used as a base class. CView includes groups of virtual functions for OLE support, document-state changes, printing, and window activation. You can customize each of these functions in any derived class. These virtual functions define the scope of customization expected in classes derived from CView. If your class includes no virtual functions, it's meant to be a concrete class. 

The CString function calls are a bit faster than the CView virtual function calls. You'll experience a small performance penalty for virtual functions, but this penalty isn't an issue with CView. The gains from treating views polymorphically far outweigh the small performance penalty from calling virtual functions. However, CString executes more quickly because it lacks virtual functions. Because the designer didn't perceive the need to derive new behaviors from CString, you can avoid the performance penalty by not declaring any functions virtual. Notice that CString is not derived from CObject, so it avoids the overhead of CObject's virtual functions. 

When you write your own classes, evaluate carefully whether you intend your class to serve as a base class. Not every class should be burdened with the extra runtime costs associated with virtual functions. On the other hand, classes that derive from your class shouldn't override any nonvirtual functions. This restriction can limit you. 

Examine Other Public Functions
Nonvirtual public functions define the interface provided by the class's implementation. CString has a large number of public functions. By examining these functions, you can easily learn that this class is meant to replace C-style character arrays. CString provides several overloaded arithmetic operators to support string comparison and concatenation. First, notice the assignment operators: Every constructor has a corresponding assignment operator. You can construct a CString from a pointer to a char, and you can also assign an existing CString to a pointer to a char: 



   const CString& operator=
      (const CString& stringSrc);
   const CString& operator= (TCHAR ch);
   const CString& operator= (char ch);
   const CString& operator= (LPCSTR lpsz);
   const CString& operator= (LPCWSTR lpsz);
   const CString& operator= (const unsigned char* psz);

This rule holds for operator +() and operator +=(). I explained this in my last column on overloading operators (see Resources). If you can create a CString from a C array, you can assign a CString to the value of a C array. Similarly, because you can concatenate two CStrings, you should be able to concatenate a C array on the end of a CString. 

CString also contains a conversion operator that converts CStrings into a C-style array. The presence of this conversion operation shows some of CString's early heritage. When CString was first developed, the C++ Standard Library was nowhere near as mature as it is now, and writing programs that mixed C and C++ code was common. The ease of using a CString in C language functions was a plus. 

A few CString methods show the class's early heritage: 



   void AFX_CDECL Format
      (LPCTSTR lpszFormat, ...);
   void AFX_CDECL Format (UINT nFormatID, ...); 
   void FormatV (LPCTSTR lpszFormat, va_list argList);

These methods, which date back to MFC's original release, let you use printf() syntax to set a CString's contents. The C++ Standard Library string class doesn't contain this style. Instead, it supports iostream-style syntax to set a string's contents. 

CView contains only one nonvirtual public method, which is yet another indicator that CView is a base class. The CView class does very little work on its own, but provides a framework for derived classes. 

Describe Class Behaviors
After dissecting the public interfaces of the CString and CView classes, examine the protected interfaces. Protected interfaces generally describe the behaviors a class provides on behalf of derived classes. You write protected functions to encapsulate implementation all derived classes can share, but the behavior is not part of the public interface for the class. 

I've already said CString shows signs that it wasn't designed to be a base class. So, I wouldn't expect CString to have protected functions because these functions define the interface provided for derived classes. However, CString does have a protected interface, and all the protected functions are part of CString's reference counting algorithms. Reference counting was added to CString for efficiency after several MFC releases (see the sidebar, "Reference Counting: Help or Hindrance?"). 

Reference-counted strings are not copied when passed to functions that don't change the string's value. Normally, I would expect the functions relating to reference counting to be protected members of CString. My best guess as to why they're protected members: Even though CString was not designed as a base class, the MFC designers were concerned about making such a change to CString's inner workings without giving users the means to circumvent that behavior. 

CView has a number of protected virtual functions. These functions, called by the MFC framework, enable derived classes to customize the class's behavior. They're not public because CView declares the other framework classes as friends; they're protected because they provide default implementations derived classes might want to use. 

After I examine the member functions a class provides, I look at what data members are accessible outside the class. I personally view public data members and protected data members with concern. They tend to freeze a class implementation because any derived classes can access them. CString contains only one protected data member that points to the C-style array containing the characters. 

CView also contains only one protected data member: the pointer to the associated document. Look at protected data members as part of your class's interface. These data members are invariants that won't change over time. In the case of CView, the CDocument pointer will always be part of CView. This is a safe, protected interface. 

The two classes I showed have different uses, and therefore different designs. Both are well-suited to the tasks they were designed for. How you structure your classes exposes your assumptions about how those classes would be used�the code structure used for a base class differs from the code structure used for a concrete class, for example. Whenever you design and implement a new class, consider carefully how the interface you define also defines the way client programmers use your class. When determining how you want to use and enhance existing classes, use these same techniques to understand the designer's original intent. The closer you come to the anticipated usage patterns, the fewer problems you'll encounter. 


Bill Wagner is the president and software architect for Midwest Seas Software Development Inc. Bill has several years of experience in Windows and C++ programming. He specializes in C++, Java, and COM-based enterprise-programming solutions. Reach him by e-mail at wwagner@midwestseas.com
 


c0Title: Distributed Computing With SOAP
c1Code:
April 2000
 

http://www.devx.com/premier/mgznarch/vcdj/2000/04apr00/dm0400/dm0400.asp
Learn how and why SOAP fits into the big picture of today's distributed computing arena. 

by Davide Marcato 


     Simple Object Access Protocol (SOAP) was born into distributed computing technology about 18 months ago as the brainchild of a few developers and researchers at DevelopMentor and Microsoft. They created SOAP to meet the needs of developers who found distributed computing difficult to deploy with DCOM and CORBA, because firewalls typically don't pass these protocols and administrators are unwilling to open the firewalls to allow them. The deployment of COM vs. the deployment of DCOM has been a study in contrast. 
What you need:
To test the early SOAP implementations made public by DevelopMentor, you need Microsoft Internet Information Server (MS IIS), a modern Web browser, and Visual C++ (or Perl).  
 
COM has been around since the early 90s, but it has achieved widespread appreciation and utilization only in the last few years. It took that long for enough real-world experience and industry feedback to be accumulated to shape the COM components into a usable infrastructure and provide enough documentation for most developers to use it. COM presents a sheer learning curve in the beginning because of the paradigm shift it forces on the typical Windows programmer, but after you get acquainted with it, its productivity and development potential more than make up for the initial effort. 

In contrast, DCOM should be easy to get started with because the fact that the component is running over the network is mostly transparent to the developer. However, DCOM has failed to achieve significant penetration. If you ask many COM programmers about their experiences with DCOM, they'll likely answer that the idea by itself is excellent, but configuration complexity and the overly complicated security model render it tough to get to work within a LAN, and nearly impossible to deploy over firewalls (typically, the gateways between corporate LANs and the Internet). 

Similar experiences characterize the opposite CORBA camp: Their Internet-Inter-ORB Protocol (IIOP) should provide the best transparent distributed communication means, but in practice it shares the drawbacks of DCOM. 

   
Figure 1. DCOM vs. SOAP. Click here.

 
It seems like all the major players in this emerging market niche, in an attempt to capture the largest share of the customer base, invested aggressively in producing the most technologically advanced solutions, overlooking some of the priorities and most compelling needs of the clients. While maybe 10 to 20 percent of the scenarios indeed benefit from and thoroughly exploit the broad range of services offered by DCOM and IIOP, the remaining 80 to 90 percent would happily trade that wealth of features for a simpler technology that guarantees the greatest interoperability in conjunction with simplicity. 

So SOAP was born. The SOAP developers have been inspired by other ongoing attempts to mix the power of remote procedure calls (RPCs) with the flexibility of XML (most notably the XML-RPC initiative). The strength of SOAP lies in its roots; it has satisfied the real needs of 80 to 90 percent of distributed computing developers. SOAP has been submitted to the Internet Engineering Task Force (IETF) as an Internet-draft specification, so it will evolve as a nonpartisan standard of distributed communication that hopefully will bridge the gap between the CORBA and DCOM camps. (For a comparison of SOAP and DCOM, see Table 1.) 

In this article, I'll show you how and why SOAP fits into the big picture of today's distributed computing arena, and use realistic comparisons to prove why you should consider it much more than just another Internet protocol. 

SOAP = RPC + HTTP + XML
From one perspective, SOAP looks like an open protocol specification that defines a uniform way of performing RPCs using HTTP as the underlying communication protocol and XML as the data serialization format. I use the expression "RPC" in a generalized sense here because SOAP has been conceived with platform and environment independence in mind since day one. Ideally, every function call that ends up invoking a remote piece of code through a network endpoint can be encapsulated in a SOAP call. This includes actual Distributed Computing Environment (DCE) RPC calls, COM/DCOM calls, CORBA calls, Java calls, and so forth. 

To understand how SOAP, HTTP, and XML fit into the big picture, consider this example of COM in a networked environment. DCOM represents the underlying network protocol and set of technical rules (communication between proxy/stub pairs, lifetime management, identity and so on) that allow COM objects and calls to cross the physical border of the single machine. The DCOM specification in turn adopts Network Data Representation (NDR) as the low-level platform-independent data format or wire protocol to serialize method calls and parameter values back and forth between the client and the server over a network wire. 

DCOM is highly efficient and flexible, but also highly complicated. One of the primary benefits of SOAP, on the other hand, is that its power does not come at the expense of simplicity. SOAP employs HTTP as the network protocol. When it comes to serializing data values and parameters, the open and strictly textual XML comes into play as the wire protocol, instead of the proprietary and binary NDR format used in DCOM. The implementations are similar (see Figure 1), but the use of XML as the data encoding representation instead of NDR provides a higher-level abstraction and greater platform and location independence. 

Every method call originating from a client (regardless of the client's nature) must first be translated into XML at run time, a task well-suited for an automatic software gateway. To guarantee the uniform interpretation of the parameters, the method name, and the return value on both parties, the SOAP protocol imposes a proprietary but generic XML vocabulary. As a result, the data the client transmits can later be parsed and understood by the server-side SOAP gateway, which will play the same role as the stub in COM/DCOM. The specification diligently covers the XML incarnation of most complex datatypes, such as structures, object references, and arrays (treated as a special case of compounded type). The specification will provide you with additional details, so you should grab a copy of it from the IETF Web site if you are interested in knowing more. 

The resulting XML file, the name of the SOAP endpoint (the remote method name), and some other protocol-specific information is then encapsulated in an HTTP request (in the form of an HTTP POST packet) and sent to the server. The server can then send a response HTTP packet back with results to the client, if the application so demands. To mark its difference from a regular HTTP GET request for an HTML page, the caller sets a small number of HTTP headers that signal to the target service a special SOAP service invocation is being transported by the HTTP packet. 

As an example, consider the ubiquitous sample application that monitors stock prices. A server could have a component that provides the current price of a particular stock in response to a method call on a COM or CORBA component on the server. A client could then send a SOAP request to the server asking for the price of the stock. The server could call the appropriate method on the component using embedded HTML objects, or whatever means it wanted depending on the SOAP gateway in use on the server. The server could then respond back to the client with a SOAP response with the value of the price. 

This code shows how the SOAP-request HTML message would look for this example: 



POST /StockPrice HTTP/1.1
Host: www.stockpriceserver.com
Content-Type: text/xml
Content-Length: nnnn

<StockPriceServerCall>
   <GetStockPrice>
      <symbol>MSFT</symbol>
   </GetStockPrice>
</StockPriceServerCall>

The first four lines form a basic HTML header specifying the HTML message type, the host (server), the XML content type, and the length of the message content. The XML tags delimit whatever content you want, as long as the server can understand it. In this case, it's a call to the server to provide a stock price for a stock symbol of MSFT. 

The response message from the server would again contain a simple HTML response header and the XML content using SOAP protocol rules to delimit the content and method or parameter calls: 



HTTP/1.1 200 OK
Content-Type: text/xml
Content-Length: nnnn

<StockPriceServerResponse>
   <CurrentStockPrice>105</ CurrentStockPrice >
</StockPriceServerResponse>

In addition to what you see here, you can add legal HTML header content, and increase the complexity of the XML tags to allow more intricate behavior according to the SOAP specification. You can find a slightly more complex version of this sample in the Internet-draft specification (see Links). 

You can use SOAP to take this sample a step further in complexity by actually allowing the client to modify the value of the stock on the server. Do this by sending the value as a parameter, similar to the return value in the response message. You can frame almost any remote method call in a similar manner, simply by using XML tags for the method name, and additional nested XML tags for the parameter names and/or values. 

Propose the Best, Impose the Least
A paramount imperative leading the SOAP effort was to keep the protocol complete enough to be useful, but as simple as possible beyond that point. The motto I use to summarize this spirit: Propose the best, impose the least. 

Recall that SOAP was built from two simple and well-known standards (HTTP and XML) and furnished with the smallest possible XML vocabulary to package the essential data for an RPC. As such, it will not take ages for you to learn how to interface with it. One of SOAP's essential design goals was for the protocol specification to be as concise as possible, so that the protocol could be easily understood and adapted by programmers and organizations who can't afford to spend months on such a collateral project. 

The secret of the success of many other widely adopted protocols is just that: offering essential services with the lowest learning curve. HTTP is probably the most extreme and familiar example in this context. Given the popularity of the Web, one of the first applications developed for new operating systems is the browser, which acts as an HTTP client. Plus, free XML parsing engines abound on the Internet. Even the choice of two textual protocols hasn't been random: ASCII strings might be less efficient than their binary counterparts, but your testing and debugging will become easier, because you'll be able to read the actual bytes that travel through the network. 

SOAP's designers deliberately left out of the main specification everything that extended beyond this core feature set, such as object models, object lifetime rules (SOAP translates single requests and doesn't know how to identify a distributed object across calls), and security. Does this imply you can't have these features with SOAP? Not at all, but you must find companion technologies that provide those amenities, leaving SOAP only for the nitty-gritty transmission plumbing. For instance, many programmers want to map requests received on the server-side endpoint with true COM method calls on a server object, returning the results again through SOAP packets (actually encapsulated by HTTP packets). This is the role of the numerous gateways that translate requests and responses back and forth between the SOAP infrastructure and your language of choice. According to the latest announcements and promises, most of these gateways will have this capability soon, resulting in SOAP-enabling of your favorite development tool. 

Independence, Security, Performance
Recall that if you compare COM/DCOM to SOAP, there are three conceptual sides in a complete distributed computing technology�the binary specification, the network protocol, and the wire protocol; the last two matter only in remote cases. SOAP guarantees total platform and language independence by adopting well-established platform independent Internet standards for those roles, namely HTTP and XML. 

Also recall that the idea of performing simplified RPC over text-based transport protocols using XML as the wire data format was not born with SOAP. HTTP is another example, but the concept would also apply to Simple Mail Transfer Protocol (SMTP) or Microsoft Message Queue Server (MSMQ). Then why is SOAP in a better position than similarly targeted draft protocols? Well, the people in charge of shaping up the specification have struggled to keep it absolutely pure and agnostic of any details or technical choices that might suggest a bias towards any platform, programming language, object model, or operating system. Their result is as platform independent as HTML and HTTP, meaning you can employ SOAP to execute RPCs between any combination of otherwise incompatible platforms. 

At the time of this writing, alpha and beta releases of SOAP gateways existed or were underway for Perl, COM, Java, CORBA, and many others. You might want to join the public SOAP-l mailing list to keep track of the evolution of the works (http://discuss.develop.com). 

What about security? Nothing is easier to spy on than textual XML strings. No worries�you can protect the HTTP packets from malicious eyes through Web encryption protocols such as Secure Sockets Layer (SSL) and HyperText Transfer Protocol Secure (HTTPS). Someone could object that state-of-the-art DCOM security offers much more finely tuned options and selective schemes than SSL does. There cannot be a one-size-fits-all solution to this type of problem. SOAP security targets 80 to 90 percent of the projects where DCOM was overkill, a nightmare to configure correctly in nontrivial environments. This brought more pain and frustration than added value to the project. 

It's nontrivial to get DCOM calls to work when a firewall sits between the client and the server. Sometimes this restriction cannot be removed for a variety of reasons. Because SOAP requests travel over the wire wrapped by HTTP packets, they can work undisturbed through all firewalls. And while it's true that the presence of recognizable HTTP headers can be exploited to block certain types of calls directly on the firewall, the bottom line that the developer doesn't need to manipulate the firewall simply to get the first calls through. This is another significant advantage of SOAP and a big motivation in favor of reliance on HTTP. 

But all these goodies can't come without at least some minor disadvantages. 

The first drawback is the relatively high footprint and parsing overhead involved in processing a SOAP request compared to, say, an equivalent DCOM or Java RMI method invocation. This stems directly from the use of a hierarchical textual language such as XML. This parsing overhead mostly affects processor requirements, not total call execution time. The predominant environment in which SOAP was conceived to work was the Internet, and the message transmission time over a WAN dwarfs the amount of time it takes to parse the XML. 

The second drawback, at least for the short term, is that SOAP is still in an evolutionary stage. The first SOAP processors are just starting to appear, and interoperability problems will inevitably exist in the early versions. It will take some time for industry implementations to work together. Also, the standard will undoubtedly be updated as deployment happens in the real world and changes are made to accommodate real-world usage. 

What SOAP Isn't
It's important to understand what SOAP isn't so you don't have unrealistic expectations. SOAP is a replacement for binary RPC. RPC is a low-level piece of a distributed computing architecture. DCOM, for example, is built on top of RPC. Therefore, many of the services found in DCOM won't be available in SOAP. 

On the upside, the gateways that will soon ship from various vendors promise to tackle this problem and smoothly reimplement the object-RPC features that SOAP itself does not understand. For example, there is no reason why DCOM could not be implemented on top of SOAP. It would be a replacement for the binary RPC that DCOM currently uses. Microsoft has not committed to such an implementation, but has publicly announced support for SOAP. 

Another important feature of COM/DCOM you won't find in SOAP is the GUID. There is no unique ID to identify objects and interfaces. Also, there is no API enumeration, which Automation uses to expose its interface to scripting. There are no thread pools, which free-threaded COM objects use to service multiple requests. All the services we usually take for granted revolving around pure method calls won't be provided out of the box. 

A new technology's success is always driven by adoption, and it takes early adopters who are willing to put up with the early problems to create a large enough critical mass to push the technology to the mass market. The result will be worth the effort for SOAP. Server-to-server communication on intranets will continue to be served by DCOM, IIOP, Java RMI, and other traditional protocols. However, SOAP is the first protocol allowing for a communication path over a WAN with a high probability of success on Internet connections in the corporate world. 

To start using SOAP, you will need a SOAP gateway on the Internet server. DevelopMentor is working on gateways in Perl and Java that you can download from its site. After you get the gateway, try implementing a client/server communication path with SOAP. Participate in the discussion groups (http://discuss.develop.com/soap.html) and help drive the evolution of the standard. Several commercial companies have also announced support for SOAP, including Microsoft (in Windows DNA 2000) and Rogue Wave Software. Encourage more to get on the bandwagon. Start talking to vendors about why they should support SOAP and why it will improve their products for your applications. 

Once your environment is built, reassess which applications you have in progress that would be simplified or made feasible by a protocol like SOAP. Categories that are particularly relevant include: 


COM/CORBA interoperability 
Server-to-server communications between companies with incompatible systems, as is often found with electronic data interchange (EDI) 
Client-to-server communication over the Internet, such as remote offices communicating with a central server 
For more ideas on how you can anticipate working with SOAP, see the sidebar, "Planning for SOAP." 

Although nobody has a crystal ball, I envision a successful future for the SOAP initiative, probably in conjunction with a parallel standard defining business-oriented data formats in terms of XML schemas. SOAP provides the first ray of hope for software development juggernauts to cooperate seriously, at least on the data formats and lower-level RPC protocols. 


Davide Marcato is president and founder of Marcato Consulting (www.marcatocons.com), a software development and consulting firm specializing in Windows DNA and Internet enterprise solutions, especially for the e-commerce and financial fields. Contact him at www.DavideMarcato.com
 


c0Title: DLL Maintenance Made Easy
c1Code:
November/December 1999
 
Writing a DLL can seem deceptively easy�until it's time to revise it. 

by Geoff Vandegrift 


Sooner or later, in an attempt to follow the Windows code-sharing philosophy, just about every software developer will take a shot at writing a DLL. There is an abundance of information on the mechanics involved and answers to such questions as, "How is a DLL loaded," "How are classes and functions exported," and "What compiler switches need to be set?" However, all of this detailed "how-to" information won't totally eliminate the frustrations involved in writing DLLs. 
Scope of this article
Authoring DLLs is a very large topic, and this is not intended to be an exhaustive treatment of the subject. Rather, this is an attempt to pull together some fundamental concepts�such as heap independence and class backward compatibility�that can help C++ developers avoid some of the larger DLL headaches. 

Implicit versus explicit linking
Even though Microsoft's online documentation covers the topic quite thoroughly, it will be useful to briefly discuss implicit vs. explicit linking. Implicitly linked DLLs are loaded while the executable is loaded (this behavior is somewhat improved by the delay-load facility of Visual C++ 6.0's linker). To make this happen, the application using the DLL must link with an export library generated by the linker when the DLL was compiled. The DLL must then be placed somewhere on the search path (the details of this can be found in the official MSDN documentation). If Windows can't find the DLL, it will fail launching the application with a message indicating which DLL can't be found. 

For an executable to explicitly link to a DLL, it must know ahead of time what the exported functions are. Then it "explicitly" loads the library at run-time with a call to the LoadLibrary() Win32 API. For every function the application wants to access, it must call GetProcAddress(). In this case, the DLL is never loaded if the code that uses it is never called. The advantages and disadvantages of these two options will become clear later. 

One big happy memory space (sort of)
When learning to work in Windows 98/NT, developers are told that everything in a single process looks at the same, flat, 4GB memory space. Some developers then cavalierly pass pointers around, glad they never have to look at the word "far" again. It's not uncommon to see memory allocated in a DLL and passed to the parent executable that frees it; everything seems to work smoothly until the day a debug DLL is run with a release executable. What happened? Now the program that was working smoothly is suddenly crashing everywhere. 

What Microsoft could have communicated better (even though it seems obvious in hindsight) is that memory must be allocated and freed from the same heap. Because the heap being used is decided on a per module basis, any time a new module is loaded, either DLL or EXE, the heap must be specified. 

In Microsoft Visual C++ 6.0, the default heap for debug configurations is the multi-threaded debug heap. For release configurations, it's the multi-threaded release heap. This is why an executable and DLL that pass memory between each other will work fine so long as they are either both release targets or both debug targets. If memory is allocated on one heap and then given to a different heap to free, the second heap will, of course, be unable to find the memory to free, and a crash will occur. 

The simplistic solution to this problem is "always use the same heap." If that works in a particular situation, great! However, it isn't always that easy. Sometimes the executable isn't available in a version that has the desired heap. Often, large applications will allow third parties to develop "extension" DLLs or "plug-ins" to enhance the functionality of the parent application. In some of these scenarios, memory will be passed between the parent application and the extension module. If the executable is poorly written, the third-party programmer must match the heap of the parent app (which will inevitably be a release build), making debugging difficult. 

A better solution is to always "wrap" memory allocations and de-allocations. It is not uncommon for a module, either DLL or EXE, to allocate some sort of data structure, fill it with meaningful data, and hand it over to another module (a database front-end, for example) that will take ownership of the data. The second module is then responsible for freeing the memory (once it has filed the data to disk, deleted it, etc.). To make this work "cross-heap," the second module should export a data structure allocation function. The first module can then call that function to allocate the new instance of the data structure (rather than allocating directly). It can fill in everything in the data structure and hand it over to the second module without fear of what will happen when the memory is eventually de-allocated: 


//
// Exports.h - Contained in a database support DLL
//
#define MAX_NAME    1024
typedef struct {
char szName[MAX_NAME]; int age;
} SRecord;
SRecord *newRec(void);
bool addRec(SRecord *pRecord);

//
// Exports.cpp - Contained in a database support DLL
//
SRecord *newRec(void)
{
return (SRecord *)malloc(sizeof(SRecord));
}

bool addRec(SRecord *pRecord)
{
bool bStat = true;

// 
// Do something with the record
    // .
    // .
    // .

// Now that we're done with the record, free it free(pRecord);
return bStat;
}

//
// Client.cpp - Contained in an executable that uses the database
// support DLL.
//
bool addToDB(const char *szName, const char *szPhone, int age)
{
bool bStat = true;
// Allocate through wrapper function
SRecord *pRecord = newRec();

if (pRecord) {
strcpy(pRecord->szName, szName); pRecord->age = age;
// Hand pointer "ownership" over to database
bStat = addRec(pRecord);
    }
else {
bStat = false;
    }

return bStat;
}
It's important to understand that memory allocated on a particular heap can be accessed (for both read and write) by any module no matter what heap it is using. The problem arises only during allocation and de-allocation. If you bear this in mind, you can avoid other, less obvious problems. For example, you must be careful when passing classes that allocate memory between modules. As is the case with MFC, a module can dynamically link with either the debug version or the release version. 

Suppose two DLLs pass CStrings back and forth, and one module is linking with the debug version of MFC and the other is linking with the release version. If the CString object is created in one module and passed to the other, the other module can cause a crash by calling a CString method that induces the object to do a de-allocation. See the following code segment for an example: 


//
// Exports.h - Contained in support DLL using debug version of MFC
//
void appendString(CString &str);

//
// Exports.cpp - Contained in support DLL using debug version of 
// MFC
//
void appendString(CString &str)
{
// operator+= can potentially cause a memory de-allocation.
// Since str is a reference, we will be freeing memory that was
// allocated in the calling routine.  str += "2nd String";
// CRASH!!
}

//
// Sample.cpp - Contained in an EXE using the release version of 
// MFC
//
void foo(void)
{
CString str("1st String");
appendString(str);
AfxMessageBox(str);
}
Even if you're careful about which CString methods are used on both sides of the module boundary, you could still experience problems if the next version of MFC comes out with methods that are no longer safe. 

By making sure that all modules are "heap-safe," you can avoid many headaches. For an excellent discussion of Win32 memory space, see Jeffrey Richter's book Advanced Windows (for more information, see the "Resources" section). 

Backward compatibility
In the days of C libraries, backward compatibility was relatively straightforward. So long as you didn't change the signature of the function, and did thorough testing to make sure the internal changes didn't break any existing dependencies, all was well. 

However, C++ confronts you with exporting classes. It seems the only thing that should matter for backward compatibility is the public interface, i.e., so long as the "signature" of the public interface doesn't change, backward compatibility should be maintained. Nothing could be further from the truth! The insidious thing about classes is found in their representation in memory. Remember that the size of a class is the sum of the sizes of its member variables plus the size of a function pointer if the class contains any virtual functions (four bytes in Win32). Developers often make the mistake of adding or removing private members in an exported class, expecting not to break backward compatibility. By doing so, the new DLL is dropped into place, and suddenly, the previously working application is broken in a very unpredictable fashion. The problem is that the parent application still thinks that the class is the old size and is allocating space for it accordingly. 

Suppose an integer member has been added to an exported class. Instances of this class are now four bytes larger. The parent application creates an instance of the class (with the new DLL in place). Because it hasn't recompiled with the new header, the application still thinks the class should be its original size. At some point, the application will call the method that uses this new integer. The "class code" residing in the DLL will look at the integer and get random memory because the space for the integer was never allocated. Suddenly, encapsulation doesn't seem so encapsulating! 

To borrow a term used by John Lakos, author of Large Scale C++ Software Design (see the Resources section for more information), what is needed here is "insulation." Lakos defines insulation as "a contained implementation detail (type, data, or function) that can be altered, added, or removed without forcing clients to recompile" (Lakos, page 332). There are many ways to insulate a class; we'll consider two primary forms of insulation: an abstract base class (or protocol class) and a fully insulated concrete class. Of course, each has its own benefits and drawbacks. 

An abstract base class is entirely pure virtual except for the destructor (Lakos, page 386). By itself, such a class is useless. It needs to have a concrete class that inherits from it somewhere. This is where the work of the class is actually done. In addition, there must be some way to instantiate the class. This relates to the "wrapper" idea discussed earlier. You can simply export "new<Class>" and "delete<Class>" functions to create and destroy the class. 

Inside of these exports, you can then do either a new or a delete on the concrete sub-class. This way, whenever a new member variable is added, it is added to the concrete sub-class with no consequences to the exported abstract class. The exported class always remains a simple four bytes in size (pointer to the v-table). This is very similar to the approach taken by COM. See the following code snippet: 


//
// Abstract.h
//
class CAbstract
{
public:
virtual ~CAbstract();
virtual void set(int n) = 0;
virtual int get(void) const = 0;
};

CAbstract *newAbstract(int n);
void deleteAbstract(CAbstract *p);

//
// Concrete.h
//
class CConcrete : public CAbstract
{
public:
CConcrete(int n);
~CConcrete();
void set(int n);
int get(void) const;

private:
int m_n;
};

//
// Abstract.cpp
//
CAbstract::~CAbstract()
{
}

CAbstract *newAbstract(int n)
{
return (CAbstract *) new CConcrete(n);
}

void deleteAbstract(CAbstract *p)
{
delete (CConcrete *)p;
}

//
// Concrete.cpp
//
CConcrete::CConcrete(int n)
: m_n(n)
{
}

CConcrete::~CConcrete()
{
}

void CConcrete::set(int n)
{
m_n = n;
}

int CConcrete::get(void) const
{
return m_n;
}
One disadvantage to this approach that is immediately obvious is that it's impossible to create an automatic instance of this class on the stack. A fully insulated concrete class is the solution to this (Lakos, page 398). Instead of hiding behind an abstract base class, why not hide all of the important stuff behind an opaque data structure pointer that contains all of the member variables, as illustrated in the following code: 


//
// Sample.h
//
struct CSampleImp;
class CSample
{
public:
CSample();
~CSample();
int get() const;
private:
CSampleImp *m_this;
};

//
// Sample.cpp
//
struct CSampleImp {
int a; int b;
};

CSample::CSample()
: m_this(new CSampleImp)
{
m_this->a = 1;
m_this->b = 2;
}

CSample::~CSample()
{
delete m_this;
}

int CSample::get() const
{
return m_this->a;
}
In the constructor, allocate the memory that will contain all of the member variables. That way each instance of the class carries a unique pointer to its own, unique data structure. Be sure to free the allocated memory in the destructor, and every time a data member is accessed, just remember to do it through the structure. 

Every careful developer must be ready for the allocation to fail. (See the sample code above.) However, there is no way to return a failure from a constructor because it must always return void. It isn't a huge issue because the data structure is generally quite small, and Windows will essentially never refuse such a small allocation request. For those who like to look for a NULL return, this is one advantage of the abstract base class. The exported constructor can actually return NULL if the allocation fails. 

Returning to our earlier discussion of implicit vs. explicit linking: In the case of a fully insulated concrete class, you must link implicitly. There is no way to "load" on a class. Instead, you must use the compiler's trick to export a class (see the keyword __declspec for Visual C++). An abstract base class allows you to link either explicitly or implicitly because the "class allocation" routine is exported as a function. 

   
Figure 1 Click here.

 
Inheritance is one last item to consider in weighing these two approaches against each other. Often, a DLL will be exporting a potentially large class hierarchy. This can be a problem with the abstract base class: It's impossible for one exported abstract base class to inherit from another. Let's say two abstract base classes are represented as CBaseA and CBaseB, and their implementation classes are represented as CSubA and CSubB. If you attempt to make CBaseB inherit from CBaseA, CSubB will not be instantiable because the virtual functions in CBaseA that were not over-ridden in CBaseB will never be defined (see Figure 1). 

In addition, it's impossible for a client to inherit from an abstract base class. Remember that the "constructor" for an abstract base class is contained inside of an exported wrapper function. Therefore, there is no way for a subclass to correctly call the base class's real constructor. 

That covers the problems and pitfalls of class attributes, but what about methods? 

Methods
When object-oriented programming first came on the scene, objects were always said to contain both code and data. If there were two instances of the same class, each had its own copy of the class code in memory. It was very inefficient, but that's how it was described. However, that notion didn't last long as developers began to implement this stuff in the real world. In reality, each object is just a data structure that is "operated on" by the class code. With this in mind, you can begin to get a sense of what can and can't be done with methods while maintaining backward compatibility. 

Of course, you must never remove a method; that would be like removing an exported function from a "straight C" library. It will cause the executable that uses the DLL to fail with an "Entry Point Not Found" error. (The MessageBox() will actually list the decorated name of the entry point it was unable to find.) 

On the other side of the coin, adding both virtual and non-virtual methods to a fully insulating concrete class is fine. This is a bit confusing, but the thing to remember here is that the virtual function table for a class is created at run-time during object construction. 

Therefore, when the OS builds the table, it is filled-in based on the exported decorated names of the virtual methods. These decorated names can be viewed by executing "dumpbin /exports <file>.dll". Therefore, there is no risk of accidentally slipping a new virtual function into the middle of the v-table of an exported class's sub-class, thereby potentially causing the wrong virtual function to be called. There is one caveat: to add a virtual function and still maintain backward compatibility, the class must already contain a virtual function. Otherwise, the class will grow in size (pointer to the v-table). Because many people make a habit of declaring all destructors as virtual, it's generally not a problem to add virtual functions. 

Abstract base classes are a different story. In this case, because the object is constructed inside the exporting module, the virtual function table is also created inside the exporting module. The existing code in the client module is accessing virtual methods by offset into this virtual function table. Therefore, if the table changes because a new method has been added, the client module may or may not be calling the correct method. 

One must also be on guard for default parameters (Lakos, page 346). What if the default value changes over time? The DLL loses backward compatibility. Default parameters actually get moved to the code that makes the call (not the function with the default parameter). Because of this, the parent module still thinks that the default parameter has the old value; and the function receives the old value instead of what it knows to be the default parameter. Be very careful when defaulting parameters. You must consider the ramifications of never being able to change a default parameter and be convinced that's acceptable. 

Inline functions are, of course, the most blatant violators of backward compatibility (Lakos, page 339). If the code is actually moved in-line (which isn't always guaranteed), then the minute the code changes, the old parent module doesn't have it, and the DLL has lost backward compatibility. 

Classes: enough already!
One final issue to consider in regard to the backward compatibility of classes exported from DLLs is enumerations (Lakos, page 347). If used to represent a constant in the header, the minute the constant changes, backward compatibility has been compromised (in similar fashion to default parameters). Return codes are another common use for enumerations in a class. The risk here is in adding a new return code. If the class previously had one success code and one failure code, the addition of another error code could break existing code, depending on the reaction to the return values. It's best to document in the header that additional error codes could may be added, so all clients should check for the success case rather than checking for the logical negation of the failed case. 

Of course, removing an enumeration will cause the remaining enumerations to be renumbered, thereby breaking backward compatibility, so it's best to explicitly number enumerations. 

Obviously, it's not to list every possible change that can be made to the class interface exported from a DLL. What's important is to consider them from the compiler and OS perspectives. Imagine how it will look at run-time, and make a reasonable guess as to whether a change will maintain backward compatibility. In the final analysis, nothing beats extensive backward compatibility testing. 

When all else fails and backward compatibility must be broken, don't forget to rename the DLL. Microsoft has taken the lead here with things like MFCxx.DLL. Renaming may allow you to leave the old on a system working with one application, while the newer (and renamed) DLL can be used by another application. 

A few last details
No discussion of writing libraries would be complete without a brief note on naming-conventions. It's generally a good idea to decide/agree on a prefix for all functions and classes exported from a DLL. That way, one DLL's ProcessData() function doesn't conflict with a DLL from somebody else who happens to like the name ProcessData() as well. It also makes it clear in the code where certain functions/classes reside. 

Base classes are often overlooked when writing DLLs. The base address of a DLL is the address at which Windows attempts to load it. If the address is already in use, Windows rebases the DLL to a free space in memory. This can impact performance overhead. Unfortunately, the default base address for all DLLs is 0x10000000, and developers typically don't change it. As a result, a majority of non-Microsoft DLLs end up being re-based at load time. 

Microsoft has left open the space from 0x10000000 to 0x7FFEFFFF for base addresses. The Microsoft system DLLs are based between 0x68000000 and 0x7800000000, and memory is generally allocated from the bottom up (i.e., lower addresses first). Given this, it seems reasonable to use base addresses between 0x64000000 and 0x68000000. This is, of course, in no way an absolute�only a suggestion based on a few restrictions. 

For a complete discussion on base addresses and re-basing, consult the Microsoft Developer Network documentation. 

Summary
Writing a DLL can seem deceptively simple�until it's time to revise it. There are some fundamental physical design issues that must be considered up front. Using the basic ideas presented here as a starting point, DLL authoring can be much easier. 


Geoff Vandegrift is a Senior Software Developer for Hitachi Software Global Technology Ltd. in Westminster, Colo. He can be contacted at gvandegrift@hsgt.com
 


c0Title: Expose Functions to VB Apps
c1Code:
July 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/07jul00/et0007/et0007.asp

  Level: Advanced 
C++/VC++ 

Often, when VB developers want to use a C++ function declaration, they must translate it into a VB Declare statement. Why not make it easier on them by including a type library in your C++ DLL that allows VB to set a reference to your C++ DLL? 

To export the function, declare it as Extern "C" and _stdcall. You also need to export it in your DEF file. This code�which belongs in the CPP file�exemplifies a DLL exporting the function Sum: 


extern "C" long __stdcall Sum(long x, long y) 
{ 
	return x + y; 
} 
Def file: 
LIBRARY TechTipDll 
EXPORTS 
	Sum @1 PRIVATE 

Next, create an IDL file, so the MIDL compiler can create a type library file. To create the type library from the IDL, either use midl.exe directly or just include your IDL file in your project to have DevStudio compile it for you: 


import "oaidl.idl"; 
[uuid(CBD8EA74-EA14-11d3-A28A-0008C7D3A384), 
	helpstring("TechTip Type Library"), version(1.0)] 
library TechTipLib 
{ 
	[dllname("TechTipDll.dll")] 
	module TechTipDll 
	{ 
		[entry("Sum")] long Sum([in] long x, [in] long y); 
	} 
}; 

To include the type library in your DLL, add a line like this to your project's resource file (use Notepad to edit the RC file): 


1 TYPELIB MOVEABLE PURE ".\\Debug\\TechTipDll.tlb" 

You can now set a reference to the DLL from VB. 
�Mike Hill 
 


c0Title: Extend Office With ATL Add-Ins
c1Code:
July 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/07jul00/bn1_0007/bn0007.asp
Use ATL to build COM add-ins that extend and customize the capabilities of Microsoft Office applications. 

by Brian Noyes 


   Microsoft Office 2000 includes a flexible new mechanism to let you extend the capabilities of its applications: You can create COM add-in components for additional or specialized functionality. To do this, you implement the IDTExtensibility2 interface, then use the Office application object model to access and specialize the behavior of the application. Microsoft has extended and standardized the Office object model so that if you figure out how to use the object model of one Office application, you can adapt your component to work with other Office applications with only minor modifications. 
What you need:
Visual C++ 6.0 
Microsoft Office 2000 
Internet Explorer 4.01 or later  
 

In this article, I'll show you how to create an Office COM add-in component using the Active Template Library (ATL). You'll develop it specifically for Outlook, but the same concepts apply to developing a component to work with any Office application�you just interact with different components in the application's object model. 

You need to do two things to create an Office COM add-in component: implement the IDTExtensibility2 interface in your COM component, and add some Registry entries so the target Office application recognizes your component as an add-in for that application. 

The IDTExtensibility2 interface has five methods: OnConnection(), OnDisconnection(), OnStartupComplete(), OnBeginShutdown(), and OnAddInsUpdate(). The host Office application calls these methods when the events occur. The main ones you'll probably use are OnConnection() to initialize your component and OnDisconnection() to clean up as your component dies, in a fashion similar to a constructor and destructor for a class. The other methods provide additional opportunities to react when facing events that could affect your component's state. 

You also need to add a Registry key for the target Office application to tell it that your component exists and is designed as an add-in for that application. Under each Office application's key in the HKEY_CURRENT_USER\ Software\Microsoft\Office key, there can be an \Addins key that includes keys for each add-in component for that application. The subkey of the \Addins key uses the component's ProgID or version-independent ProgID as the key name. Under this key, you can add several values to configure the component. 

The important values are the LoadBehavior flag and the FriendlyName string. The LoadBehavior flag determines when your component will be connected, and the FriendlyName string is displayed in the Office applications' COM Add-Ins dialog to identify your component and indicate its connection state (see Figure 1). Consult the MSDN documentation on the LoadBehavior flag to see the flag's possible values. The most common value is 3, which indicates the component should be connected at application startup. 

Add the MailParser Component
For a sample COM add-in component, I'll show you how to create an Outlook add-in that parses e-mail messages in your Inbox or other folders to obtain a word count. The component lets you either obtain a word count manually on messages in the currently selected folder by pressing a command bar button, or obtain the word count of unread messages in the Inbox each time a new message arrives. (Download the sample project.) 

To get started, create an ATL COM AppWizard project called MailParserSvr, and accept the defaults in the wizard by pressing Finish and OK. Then add a Simple object through the Object Wizard. To do this, select Insert | New | ATL Object from the menus, select the Simple object type in the Object Wizard, and press the Next button. Type in "MailParser" and click on OK, again accepting the defaults for the rest of the names and attributes. 

As I mentioned earlier, you must perform two steps for this component to become an Office COM add-in component. Add the right self-registration keys to identify it as an add-in for the Office applications it supports, and implement the IDTExtensibility2 interface. 

To include the self-registration key, add this script code in the MailParser.rgs file the wizard created, immediately below the rest of the self-registration script: 


HKEY_CURRENT_USER
{
   NoRemove Software
   {
      NoRemove Microsoft
      {
         NoRemove Office
         {
            NoRemove Outlook
            {
               NoRemove Addins
               {
                  ForceRemove MailParserSvr.MailParser.1
                  {
                     val FriendlyName = s 'MailParser Object'
                     val LoadBehavior = d 3
                  }
               }         
            }
         }
      }
   }
}
   
Figure 1. Add and Remove COM Add-Ins Click here.

 
This script code is pretty straightforward. It simply adds a key to the \Outlook\Addins key with the name of the ProgID of the sample component. It then adds the two values for FriendlyName and LoadBehavior, as I discussed earlier. Note that the NoRemove statements are important here. They ensure that when the component unregisters itself, it doesn't remove the rest of the tree of keys leading to that key, which would trash the functioning of most software on your system. However, the ForceRemove statement for your particular key makes sure that every time the component is registered, it removes and re-creates this key. This is the right way to approach Registry keys specific to a particular COM component for versioning and update reasons. 

The easy way to implement IDTExtensibility2: Use the new ClassView support for ATL added in Visual C++ 6.0. Right-click on the CMailParser class in the ClassView pane, and select Implement Interface from the popup menu. Find the Microsoft Add-in Designer (1.0) type library that the Office 2000 installer placed in the Program Files\Common Files\Designer folder. Check the box next to this type library and click on OK. Then select the _IDTExtensibility2 interface and click on OK. 

Visual C++ then adds an #import line to the top of your header to pull in the type library information for the add-in designer (msaddndr.tlb). It also adds code to your component's header file to include skeletal implementations of IDTExtensibility2's methods, and adds IDTExtensibility2 to your class inheritance list using the IDispatchImpl<> ATL class. Finally, Visual C++ adds an entry to your component's COM interface map so QueryInterface() calls can respond appropriately. Change the OnConnection() implementation to return a success code (such as S_OK) so it can be successfully connected in the host application. 

Import the Office and Outlook Object Models 
Next, add an #import line for the Office and Outlook type libraries so they'll have smart pointer access to their object interfaces. Enable exception handling for the component because errors that the interface methods returned were raised as _com_error exceptions by the smart pointer classes that #import generated. You do this by enabling exception handling in the C/C++ tab of the Project Settings dialog under the C++ Language category. 

Add these two #import statements, adjusting them as necessary for wherever you installed Office on your machine: 


#import "C:\Program Files\Microsoft Office\Office\mso9.dll" named_guids
#import "C:\Program Files\Microsoft Office\Office\msoutl9.olb" \ no_namespace, named_guids
using namespace Office;

   
Figure 2. Partial Outlook Object Hierarchy Click here.

 
Use the no_namespace and using namespace directives to simplify access to the interfaces generated. The named_guids directive generates the GUIDs for the interfaces and objects you'll reference. 

Make It Interactive
The first step in making the sample add-in interactive: Include some command bar controls. To do this, add a single command bar containing a single button that sends a command to the sample add-in to parse the selected messages in the current folder and display a word count. You do this with a function named AddCommandBar(), which you can find in the download code. Call this function from the OnConnection() method. You should also cache a smart pointer to the Application object in a member variable named m_pApp using the parameter passed to OnConnection(). Do this because the Application interface is the portal to access all other interfaces for the application in question. 

To understand the objects AddCommandBar() uses, see Figure 2. This figure shows the objects in the Outlook object model that you use in the sample application. To set up the command bar, first get an interface to the Explorer object using the ActiveExplorer() method of the Application interface. Then get the CommandBars collection and look for the command bar by name. 

Check whether the command bar and button exist, so you don't create multiple copies of them. If they do, just make them visible; if they don't, create them. Either way, cache a pointer named m_pButton for event handling later. You should also consult the AddCommandBar() code (see Listing 1). The best way to figure out which objects are available for the task at hand is to dig into the voluminous online documentation in MSDN for Office 2000. 

Having a button for the sample add-in doesn't do a lot of good unless you know when it has been pressed. You also want to react to an event when a new e-mail message arrives. In order to accomplish these tasks, add handlers for button press events for the sample button, and for the event Outlook dispatches when a new message arrives. As I mentioned earlier, you can do this in a couple of ways, all of which rely on the underlying COM connectionpoint mechanism. For the simplest way ATL 3.0 provides, use the IDispEventImpl<> template class (see the sidebar, "Event Handling With IDispEventImpl<>"). 

Declare the Base Event Interface Classes
IDispEventImpl<> was introduced in ATL 3.0 to work in conjunction with the CComCompositeControl<> class, but like other ATL classes, you can use it for other purposes as well. Here's the template signature for IDispEventImpl<>: 


template <UINT nID, class T, const IID* pdiid = &IID_NULL, 
const GUID* plibid = &GUID_NULL, WORD wMajor = 0, 
WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
class ATL_NO_VTABLE IDispEventImpl 
: public IDispEventSimpleImpl<nID, T, pdiid>

The first parameter is intended to be the control ID of the control that has events you're reacting to. The button doesn't have a control ID because it lives outside the sample component, so you can use an arbitrary ID for this. Next is the class name of the object�a standard parameter for most ATL templates�so they can perform a type cast on objects in the class functions. 

The next parameter is the interface IID for the event interface in the control you'll handle events from. The next three parameters specify the library GUID, major version, and minor version numbers for the event interface type library. You need to specify these so ATL can figure out the right signatures to use for interface methods. 

You can derive your object from more than one instance of IDispEventImpl<>, as shown in the example, to handle the two types of events. When you do, you'll need to scope calls to the interface methods with the base class name. If you're not a frequent user of ATL, the base class might not be apparent to you: It's the entire template declaration of IDispEventImpl<> for that control because the sample component inherits from this class. Repeating the entire template declaration can get a little messy and cause errors, so use typedefs to make coding easier. 

Add these typedefs and symbol definitions to the top of the MailParser.h file: 


#define OURBTN 101
#define APPOBJ 102
class CMailParser;
typedef IDispEventImpl<OURBTN,CMailParser, \
      &DIID__CommandBarButtonEvents, \
      &LIBID_Office,9,0> 
      BtnHandler;
typedef IDispEventImpl<APPOBJ,CMailParser, \
      &DIID_ApplicationEvents,  \
      &LIBID_Outlook,9,0> 
      AppHandler;

You must specify the library and its version numbers explicitly in the template parameters for ATL to locate the right versions of the events in the type libraries. Finally, use two #typedef statements to declare a simpler name for each base class (BtnHandler and AppHandler), which you implement to refer to the respective base class throughout the sample code. Now you can just inherit from BtnHandler and AppHandler, and scope method calls on each interface with the base class name to avoid ambiguity. 

Add the Event Sink Map
To add the event sink map, include this ATL macro code in the header (right below the message map macros is a good place): 


BEGIN_SINK_MAP(CMailParser)
   SINK_ENTRY_INFO(
      OURBTN,
      DIID__CommandBarButtonEvents, 
      0x00000001,
      OnBtnPressed,&OnClickInfo)
   SINK_ENTRY_EX(
      APPOBJ,DIID_ApplicationEvents, 
      0x0000f003,OnNewMail)
END_SINK_MAP()

SINK_ENTRY_EX() allows you to specify which interface the event is coming from when you have more than one event dispatch sink. Use this macro for the Application::NewMail() event because it doesn't have any parameters that you need to coerce. Because the CommandBarButton Click() event has dispatch parameters that represent other interfaces, use the SINK_ENTRY_INFO() macro for that event. This macro allows you to specify an _ATL_FUNC_INFO structure that the event sink handler uses to match the type library information for the parameters of the event method with the handler function signature. 

Before I get to the ATL_FUNC_INFO details, I'll cover the rest of the macro parameters. The first parameter is the control ID that you use when declaring the base class from the IDispEventImpl<> template class. This is not really a control ID, but a unique identifier for that base class. Next is the IID for the event dispatch interface you're trying to handle events from. Use the DIID values that the named_guids option created in the #import generated .tlh files. The DISPID identifies the event method on the interface�this is what ATL uses behind the scenes when the event interface calls IDispatch::Invoke(). You can use the OLE/COM Object Viewer to look up the DISPID values for the event interface methods in the type library for Outlook. 

The next parameter to the macros is the name of the handler function in your class; it's similar to a message map. Finally, the last parameter of the SINK_ENTRY_INFO() macro is the name of the _ATL_FUNC_INFO structure that specifies the function signature of the event method to be handled. To define the _ATL_FUNC_INFO structure, add this code just above the CMailParser class definition: 


static _ATL_FUNC_INFO OnClickInfo = \
         {CC_STDCALL, VT_EMPTY, 2, 
         {VT_DISPATCH,VT_BOOL}};

The _ATL_FUNC_INFO structure has four members. The first identifies the calling convention of the event methods; ActiveX components use the standard calling convention. The second is the return type of the event method, which is void in most cases. The third is the number of function parameters, and the fourth is an array of variant types that match the event method parameters. If one of the parameters is a pointer to an object type (such as CommandBarButton for the CommandBarButtonEvents::Click() method), then you need to specify VT_DISPATCH as the type in the _ATL_FUNC_INFO structure. For other unambiguous variant types such as VT_BOOL, just use their variant type specifier. 

Handle Outlook Events
The last thing you need to do to declare the event handlers: Provide member functions the code in the event sink map macros will call. You specified the names of these functions in the event sink map entries shown earlier. Simply add these function declarations to the CMailParser class and their associated bodies to the implementation file: 


private:
   void _stdcall OnNewMail();
   void _stdcall 
      OnBtnPressed(_CommandBarButton * 
      Ctrl, \
      VARIANT_BOOL * CancelDefault);

The event sink map coerces the method parameters to the appropriate interface type for you. 
Now you have all the wiring in place to handle the two events that interest you: Click() events from the command bar button and NewMail() events from the Application object. But so far, Outlook doesn't know you're ready and waiting to handle those events. To let it know, call IDispEventImpl<>::DispEventAdvise() for the appropriate base class in OnConnection(), passing it the interface pointer for the object you want events from. Then, in the OnDisconnection() method, call DispEventUnadvise() to shut off notification. 

After all that work, what's left? Well, your handlers don't actually do anything yet. But the good news is that the hard part is over. From here, it's straightforward to access and use COM objects in the Office object hierarchy as you want. You can eventually get to any of the objects in the Outlook hierarchy through the cached Application pointer. In this case, you'll deal with the Explorer object's Selection collection property when the command button is pressed, and the Inbox MAPIFolder's Items collection when new mail arrives (see Figure 2 to locate these in the object hierarchy). 

To handle the events, the OnBtnPressed() function gets hold of the Selection collection object from the Explorer object. It then loops through each item in that collection, checks whether it's a MailItem object, and if so, parses the message body and displays to the user the results of a word count. The OnNewMail() function does a similar thing, but accesses the messages by getting the Items collection of the Inbox object after obtaining the Inbox MAPIFolder from the Namespace object. It loops through each of the items, makes sure they're mail messages, checks whether they're unread, parses the unread ones, and displays the word count. 

See the downloadable MailParser project for the source code for these functions. The code is well commented, and should help fill in the blanks from the descriptions discussed in this article. 

I've covered quite a bit a ground in this article, and hopefully, you now have a good idea of how to code Office COM add-in components using ATL. The same basic steps I've gone through in developing an Outlook-specific add-in apply to any other Office application. Through this simple example, I've shown a lot of the manipulations and navigation techniques you'll need to extend and exploit the Office objects and applications to meet your needs. 


Brian Noyes is an independent software consultant with DomeWorks Software (http://domeworks.com). He's an MCSD with nine years of software development, project management, and test and evaluation experience. He's a technical reviewer and occasional author for Visual C++ Developers Journal. You can reach him at bnoyes@domeworks.com
 


c0Title: Extract ODBC-Based Data
c1Code:
June 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/06jun00/bb0600/bb0600.asp
Learn to build a data-extraction utility that supports multiple extraction formats. 

by Tom Creighton 


   I'm always moving data from one DBMS to another, or pulling data out of one for backup. Most of the database products I use have a built-in data-extraction utility. Unfortunately, the utility is different for each product, and some extract data only in a format that can be imported back into that DBMS, and not others. In any case, I've wanted my own data-extraction tool for some time. While I've often built pieces of this sort of utility, I recently sat down and built the whole thing. In the first of this two-part series, I'll show you how to build a data-extraction utility, and I'll reveal some ways you can use it to make your data-extraction tasks easier and faster. 
What you need:
Visual C++ 6.0
ODBC 3.0  
 
Before you build a tool, you need to decide what tasks you want it to accomplish. I want this utility to support table- and view-oriented data extraction. In other words, I want it to easily specify a table or view and get the data out in a variety of ways. I want the utility to support multiple extraction formats, including SQL INSERT statements, comma-separated values (CSV), XML, and custom format. I want it to specify the data source through a SQL SELECT statement, and to support multiple table extractions into one extract file. I also want it to put the output file in text for easy editing and viewing, and to support multiple data sources and multiple data targets�such as DBMSs. Plus, I want to build this so other people can use it and build on it. 

I based this utility on ODBC 3.0, although you can change it to work for 2.0 without much trouble. By basing the code on ODBC rather than some of the other database abstractions available from Microsoft, you should be able to more easily reuse this code in a variety of situations. In this utility, error checking and handling are minimal. You might want to extend these functions yourself. For example, I examine ODBC error states only in one place. If you're creating production code, you should probably examine the error states in every exceptional condition. 

Look at how the source file names map to class declarations or implementations (see Table 1). You should be able to find your way around with this guide and with the class diagram I'll discuss momentarily. (Download the source code for this project.) When you build your project, create a console application (standard Win32), then add each of the source files to it. Don't forget that VC++ creates stdafx.h for you, so copy the source files from the Web site after you create the project. I called my project vcdbextract. If you choose a different name, copy the contents of VCDBExtract.cpp to your main CPP file, or do some other appropriate fix. 

The class diagram and implementation are simple (see Figure 1). Notice the derivations CTEXMLExtract and CTECSVExtract. These two classes represent work outside this project; you can use them as further exercises. The base class CTETableExtract does most of the real work. The derived class CTESQLExtract formats the data retrieved by the base class and presents it as a SQL INSERT statement. Finally, the class CTETableDump, which derives from CTESQLExtract, formats some comments around the insert statements. 

    
Figure 1. The class diagram and implementation Click here.

 
Work With Sample Data
Before diving into how the data extraction is done, look at some sample data and associated output from the extraction utility. You'll use data in an Employee table within an Access database (see Table 2). Notice that Fred was hired around two in the afternoon. It's obviously not a government agency, because Thaddius was hired after 5 p.m. Based on the data in the Employee table, the extract tool produces the output shown in Listing 1. The output is SQL code you can run through a utility that interprets and submits the code to an ODBC data source. The output doesn't necessarily have to go back to the same DBMS type, or even the same table. You might want to look at the command-line arguments now, which you can view by running the program at the command line: 



P:\VCDBExtract\Debug>vcdbextract

You must at least provide a data source name (DSN) and table name. Here are the parameters: 



   -UN=<UserName>
   -PW=<Password>
   -DB=<data source name>
   -DTN=<destination table name>
   -STN=<source table name>
   -OF=<Output Format>

Here's the command to produce the output in Listing 1: 



vcdbextract -DB=ExtTest-STN=Employee > Extract.sql

Because my data source was Access, I didn't need a UserName or Password. I didn't specify a destination table name, and the program selected the same name as the source table name. Output goes to standard output, making it easy to collect many table extractions into one output file. The output format argument is intended as a future upgrade. 

I created this project as a console application. I don't use the Microsoft Foundation Class Library (MFC), but I do use the Standard Template Library (STL). One source file you'll find is called TEDataTypes.h, where I define several constants and datatypes used throughout the code. Because most of the code I write is used (and abused) by other people, I try to create it so users can change it into some other form. For example, I use the typedef statement to define some datatypes that bridge between ODBC datatypes and the class user (see Listing 2). 

You'll also find simple Date, Time, and DateTime classes declared and implemented in TEDataTypes.h, simplifying the interface to ODBC (I'll write more about this later). Finally, the most important thing to remember about TEDataTypes.h: the return type definition�TERetType. This enumerated type defines the return values of all the class methods that actually do the data extraction (see Listing 3). 

The Real Work
Now that you know what DBExtract does, look at how it gets the job done. Because this is a console application, it contains a main() function (see Listing 4). Notice that I use the STL class string. This is a powerful class, but I'm not extensively using the class capabilities. Nevertheless, you'll find string variables throughout my code. The first part of the main function gathers the command-line arguments and loads the values into appropriate string variables, declared as automatic variables inside main(). I'll copy these later into data members of a CTETableDump instance. 

I extensively use C++ class properties introduced in VC++ 6.0. (see the sidebar, "C++ Class Properties" ) The base class CTETableExtract declares these properties (see the source code for the full syntax): 



   // Property declarations
   int     mcRows;
   string   mDatabaseName;
   string   mPassword;
   string   mSQL;
   string   mDestTableName;
   string   mSourceTableName;
   string   mUserName;
   bool   mbConnected;
   bool   mbDebug;

CTETableDump publicly derives directly from CTESQLExtract, and indirectly from CTETableExtract. The ExtractTo method is the only significant addition CTETableDump makes to CTESQLExtract, but it's not the only addition. CTETableDump also declares OutputWithPrefix(): 



   virtual TERetType ExtractTo(FILE * fp);

The rest of main()�I've omitted prompts for command-line arguments�looks like this: 



if (   DBDataSource.length() &&
     SourceTableName.length())
   {
      // Do something useful

      CTETableDump TBDump;

      TBDump.mDatabaseName = DBDataSource;
      TBDump.mSourceTableName = SourceTableName;
      TBDump.mDestTableName = DestTableName;
      TBDump.mUserName = UserName;
      TBDump.mPassword = Password;

      TBDump.ExtractTo(stdout);
   }

A Class Act
CTETableDump::ExtractTo does the interesting work in the program. Before looking at how it works, take a brief peek at the salient portions of CTESQLExtract and CTETableExtract, starting with the base class. You've already looked at the properties, so I'll skip that and the associated Getters and Setters. Declare the public methods next: 



virtual TERetType 
   Connect (const string & DSN = string(""));
virtual TERetType
   Connect (const string & DSN,
            const string & UserName,
            const string & Password);

virtual TERetType Disconnect ();
virtual TERetType 
   Execute (const string & SQL = String(""));
virtual TERetType 
   GetColumnType (TEUShort ColumnID,
            eColumnType & ColType);
virtual TERetType 
   GetNextRecord (string & Record);
virtual TERetType ProduceSQL ();

You can connect to the database in two ways. One requires a username and password; both require an ODBC data source name. If your database doesn't need a user login, you don't need to provide the username and password. The Disconnect() method severs the connection to the database. You call Execute() to actually perform a SQL query. A call to GetColumnType tells you the type of any of the columns in a resultset. GetNextRecord() allows you to cycle through all the records in the resultset. Finally, use ProduceSQL() to generate the actual SQL query used in Execute(), in case the statement isn't passed into Execute(). CTETableExtract declares several protected properties and methods, and several private data elements referred to by the public and protected properties. I'll go over some of these later. 

CTESQLExtract derives from CTETableExtract. Besides the constructor and destructor, CTESQLExtract declares only one method: 



virtual TERetType 
   GetNextRecord (string & Record);

You call GetNextRecord() and ProduceSQL() from CTETableDump::ExtractTo. Here's a condensed listing of the ExtractTo() method: 



TERetType CTETableDump :: 
   ExtractTo (FILE * fp)
{
<declare auto variables>
<get date/time>

   // Ensure SQL statement is ready
   RetCode = ProduceSQL();

   <format output to file>
   <generate extract header info>
      RetCode = Connect();
      RetCode = Execute();

      for (RetCode = GetNextRecord(Record);
               TE_OK == RetCode;
               RetCode = GetNextRecord(Record))
   {
      fprintf(fp, "%s\n", Record.c_str());
   }

   <Output extract footer>
}

To use this method, you simply pass in a pointer to an open stream (FILE *). In this case, it's stdout, but you could code up something that would output to a specific file, and CTETableDump would be perfectly happy to dump into it. 

ExtractTo() outputs some formatted header information to record the date and time of the extract, as well as the SQL used to do the extract. Before connecting to the database, you call ProduceSQL(), which decides the particular SQL SELECT statement you should submit to get a rowset. The SELECT will either be a simple Select * From <Source Table Name>, or the user will have sent it. If the main program had set the SQL explicitly through something like this, 



TDBDump.mSQL = 
"Select LastName, FirstName \
 From Employee\n            \
 Order By LastName";

then the output would have looked much different. The important thing to remember is that the classes support this feature, but the main program hasn't provided access to it. 

Once you've set the SQL for this extraction, ExtractTo() outputs the header information, then connects to the database. As mentioned earlier, you can call the Connect() method with a username and password. In the example, you use the default value of an empty string. By doing this, you instruct Connect() to use the values of mp_DatabaseName, mp_UserName, and mp_Password, which are data elements of CTETableExtract and are set through the mDatabaseName, mUserName, and mPassword properties, respectively. CTETableExtract::RealConnect() (a protected method) does the actual work. 

RealConnect() does the standard ODBC thing to get connected. Of course, if you've never done ODBC coding before, it might not be "standard" to you. Here's a snippet of RealConnect(): 



SQLHENV      hEnv;
SQLRETURN SQLRetCode =
      SQLAllocHandle(SQL_HANDLE_ENV,
               SQL_NULL_HANDLE, & hEnv);

if (SQL_SUCCESS == SQLRetCode)
{
   mhEnv = hEnv;

  // Declare ODBC version

   SQLSetEnvAttr(   mhEnv,
               SQL_ATTR_ODBC_VERSION,
                  (void *)SQL_OV_ODBC3,
                  0);

   // Now get a connection object

   SQLHDBC hDBC;

   SQLRetCode =
      SQLAllocHandle(SQL_HANDLE_DBC,
                  mhEnv, 
                  &hDBC);

First, RealConnect() allocates an environment handle and stores it in a private data member using the CTETableExtract property mhEnv. After getting an hEnv, it sets the proper ODBC version through a call to SQLSetEnvAttr(), then allocates a connection handle and stores it away through CTETableExtract::mhDBC. Armed with the hDBC, it can then make the actual database connection: 



if (SQL_SUCCESS == SQLRetCode)
{
   mhDBC = hDBC;

   SQLRetCode = SQLConnect(   
               mhDBC,
      (SQLCHAR *)   mDatabaseName.c_str(),
      (TEShort)   mDatabaseName.length(),
      (SQLCHAR *)   mUserName.c_str(),
      (TEShort)   mUserName.length(),
      (SQLCHAR *)   mPassword.c_str(),
      (TEShort)   mPassword.length());

   RetCode = (SQL_SUCCESS == SQLRetCode) ?
            TE_OK : TE_CANT_CONNECT;

   mbConnected = (TE_OK == RetCode);
   }

If all goes well, the method returns TE_OK. The property mbConnected records the connected state. 

Things Get Interesting
I generally define a class, and in many cases a class hierarchy, to use a set of enumerations as return values. All the classes' methods will return this type. Because of space considerations, I won't document what values each method returns. The return constants are all defined in TEDataTypes.h. 

Once you're connected to the database, ExtractTo() calls CTETableExtract::Execute() to run the SQL. I won't explain much about this method, but if you look at the source code, you'll see that I use the SQLExecDirect() API function. Some of you might be accustomed to SQLExecute(). To use SQLExecute(), you must have already "prepared" the SQL statement. Because you only want to execute this statement once (you're not setting parameters in the SQL), you should call SQLExecDirect() instead because it prepares the statement first, then executes it. 

The only other thing to note in the Execute() method: It's the only place in this program where I actually ask ODBC for more information about an error condition. You do this in ODBC 3.0 differently from the way you would in 2.0. So, when I coded this ODBC function call (OK, it was because I was chasing a bug!), I thought I'd leave it as an example. 

Now that ExtractTo() has you connected to a database and has executed your query, it's time to retrieve the data. This is where things get interesting. In this case, you want to retrieve the data formatted into SQL INSERT statements, which is exactly what CTESQLExtract::GetNextRecord() does, and basically all that CTESQLExtract does. ExtractTo() simply executes a loop, calling GetNextRecord() and writing the result to the output stream until GetNextRecord() returns something besides TE_OK. That something is usually TE_AT_LAST_RECORD, indicating, amazingly enough, that the last record in the record set has been retrieved. 

That concludes this episode of the data-extraction utility. You should now have a good grasp of the overall design of this data extraction. Having examined the class hierarchy, use of properties, and the implementation of most of the methods in the derived classes, you can now understand the details of how I implemented the base class methods. Next issue, I'll examine in detail how the data elements are extracted from each row of the resultset, and how the data elements in each row get reformatted into SQL INSERT statements. 


Tom Creighton has worked as a professional software engineer for more than 20 years. He consults in database design and in Public Key Infrastructure (PKI) development. Tom earned a B.S. in computer science from Brigham Young University, and an M.S. in computer science from the University of Southern California. Reach him by e-mail at prohacker47@hotmail
 


c0Title: Find Your Application Path
c1Code:
August 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/08aug00/et0008/et0008.asp

Level: Intermediate


When you're developing a pure ATL application, an innocent-seeming task such as resolving your application path at run time can become annoying. Here's how you get around this nuisance. 

First, create a buffer big enough to hold the maximum path length possible, and initialize the buffer with NULL characters. For compatibility between character sets, use the TCHAR datatype when you define this buffer, named pszPath in this example. 

Second, pass this buffer to the GetModuleFilename() API function, passing NULL to the first parameter, which indicates you're looking for this application's fully qualified filename. 

Third, use the appropriate version of the strrchr() function to find the last backslash ( '\' ) character in the return value, and set that or the following character to NULL, truncating the string. This code snippet uses the TCHAR datatype, so it calls the _tcsrchr() function: 

TCHAR* pszPath = new TCHAR[MAX_PATH];
memset(pszPath, 0, nBufferLen);
long nLen = GetModuleFileName( NULL, 
				pszPath, nBufferLen );
if ( nLen ) 
{
	// Find last '\' char to split path from filename
	TCHAR* pResult = _tcsrchr(pszPath, '\\');
	int nPos = pResult - pszPath + 1;
	// Set char after '\' to NULL to truncate buffer
	pszPath[nPos] = '\0';
}
The _tcsrchr() function automatically delegates to the strrchr() function for ASCII or single-byte character sets (SBCS), to the wcsrchr() function for wide-character sets, and to the _mbsrchr() function for multibyte-character sets (MBCS). 

To make it even easier for you to integrate this code into any application, you'll find a simple class, CPathUtil, in the pathutil.h file. This class provides two member functions for returning both the application path and the filename (separately) for the current application.


�Mich�le Leroux Bustamante 


Send Your Tip
If it's cool and we publish it, we'll pay you $25. If it includes code, limit code length to 20 lines if possible. Be sure to include a clear explanation of what your tip does and why it's useful. Internet: vcdjedit@fawcette.com. Post: Nina Goldschlager, Fawcette Technical Publications, 209 Hamilton Avenue, Palo Alto, CA, USA, 94301-2500. Please include your mailing address with your submission
 


c0Title: Force MFC to Recalculate Toolbar Displays
c1Code:
  http://www.devx.com/premier/mgznarch/vcdj/2000/09sep00/et0009/et0009.asp
  
Level: Intermediate 
VC++ 6.0 |  
I was recently asked to write an ATL in-place server that had to run within an MFC MDI document/view application. The ATL component had to display menus and toolbars inside the MFC application and also had to coexist with other in-place servers. Implementing the necessary in-place interfaces in ATL wasn't too difficult. Getting MFC to display the toolbars at the correct moment, however, was a pain. 

The problem revolved around the fact that MFC delays recalculation of the necessary space required for a toolbar until what it calls "idle time." During the process of in-place activation, MFC assumes an in-place server's toolbars and menus will always conform to its activation sequence. 

Force MFC to renegotiate the necessary space required for toolbars and menus by setting the main frame's m_nIdleFlags. Do this by overriding the RecalcLayout() method of the CMDIFrameWnd and OR set the m_nIdleFlags with idleNotify: 

void CMainFrame::RecalcLayout(BOOL bNotify) 
{
// Forces a redraw of the MDI associated toolbar.
	CMDIChildWnd* pMDI = MDIGetActive();
	if (pMDI)
		m_nIdleFlags |= idleNotify;

	CMDIFrameWnd::RecalcLayout(bNotify);
	RecalcAllExcept(NULL);
}
MFC recognizes (through its idle message handler) it must perform a recalculation of its toolbar display, therefore displaying any in-place toolbars. 
�Andrew Gayter
 


c0Title: Generate Rich Error Information
c1Code:
May 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/05may00/aa0500/aa0500.asp

Give your component's users more information about why method calls failed. 

by Richard Grimes 


     This column is about errors. I'm not talking about errors in your code, of course. Your code is always well designed, written, and tested�so you'll have no errors. However, these are the days of component development, and your code relies on code written by other people. You must protect yourself when their code fails. 
What you need:
Visual C++ 6.0, Service Pack 3
OLE DB (present on Windows 2000 by default; Visual Studio setup installs it on other systems)  
 
Rich error information is descriptive text that pinpoints the source of an error. You can tell your component's users if the problem arises from an invalid parameter to a method, or something more serious such as an offline database or an uninstalled component. Rich error information can give enough detail to allow users to fix the problem. In this article, I'll outline how to generate rich error information with ATL 3.0. I'll discuss some of the problems you might encounter when using standard error objects and explain how to remedy these problems using the extended error objects supplied with OLE DB. I will finish by explaining how to generate extended error objects in ATL and will present an example that demonstrates these techniques. 

COM error handling is straightforward: Every method on an interface that is marshaled must return a 32-bit status code called an HRESULT. You can define your own HRESULTs, but most developers use the codes defined by Microsoft and documented in winerror.h. These codes have tersely descriptive symbols such as E_INVALIDARG or E_POINTER, which indicate the general subject of the error. Client code can obtain these status codes and convert them to descriptive strings by passing them to FormatMessage(): 


LPSTR str;
FormatMessage(
   FORMAT_MESSAGE_ALLOCATE_BUFFER | 
   FORMAT_MESSAGE_FROM_SYSTEM 
   NULL, hrError, 0, (LPSTR)&str, 
   0, NULL);
cout << "Error: " << str;
LocalFree(str);

This code obtains the descriptive string for the code passed in hrError from the system resource DLLs in a buffer allocated with LocalAlloc(). So, if you pass E_INVALIDARG to this code, you get the string "One or more arguments are invalid." Unfortunately, this string provides no information about which particular argument is invalid or why it is in error. This is because there is no mechanism to pass method-specific error values using an HRESULT. 

The solution lies in rich error information. If your component can generate rich error information when an error occurs, it can generate a descriptive string about the error. Your component still returns an error status code, so a client knows it should ask for rich error information. So, although your method returns E_INVALIDARG, it can also return rich error information that might say something like, "There are no products in the database with this product ID; try a value between 1 and 2345." This makes debugging much easier, and allows you to provide far better error messages in the client user interface code. 

It might appear that you need to add an additional [out] parameter to every method to return this rich error information. However, COM has this covered: When a component method returns, COM checks whether the method sent rich error information, and if so, it marshals this information with the method return values automatically. COM then gives the client access to this information through an automation API. This error information is held in an error object that implements an interface called IErrorInfo. 

COM provides a standard implementation of error objects that is marshaled by value so the client accesses it through a direct, and not a marshaled, interface pointer. If you choose, you can implement your own error object and return it as long as it implements IErrorInfo. You should usually implement the custom object to be marshaled by value. 

Set Rich Error Information 
To create a standard error object, have your code call CreateErrorInfo(), which returns the ICreateErrorInfo interface. Use this interface to set the descriptive text of the error, indicate on which interface the object generated the error, and give information about a help file that can provide further details. Once the error object has been initialized, the server code calls SetErrorInfo() to make it the current error object for the thread. Each COM thread can have only one error object. Calling SetErrorInfo() a second time releases the first error object and replaces it with the second error object. Note that a thread's error object is read-only, so once it's set, you can't query it for ICreateErrorInfo to change its values. 

If the client code is in another apartment, COM ensures the error object is marshaled to the client apartment and set as the client's thread error object. The client can access this error object (usually when it gets an error status code) by calling GetErrorInfo(). 

You face two problems here: First, once error objects are set, they are read-only; second, they can hold only one error. If an error occurs many levels down in a call stack and is handled by each method setting the error object, the client gets only the error generated by the method it called! 

Supporting and Setting Rich Error Info In ATL 
Before looking at how to solve the problems of standard error objects, let's first look at how to use them in ATL. To generate rich error information, your component must support the ISupportRichErrorInfo interface. Enable this support by checking the Support ISupportErrorInfo option on the Object Wizard's Attributes page. This option adds an implementation of this method: 



STDMETHODIMP 
   CMyObj::InterfaceSupportsErrorInfo(    
   REFIID riid)
{
   static const IID* arr[] = 
   {
      &IID_IMyObj
   };
   for (int i=0; i < sizeof(arr) / 
         sizeof(arr[0]); i++)
   {
      if (InlineIsEqualGUID(*arr[i],  
            riid))
         return S_OK;
   }
   return S_FALSE;
}

The static array, arr, must contain the IIDs of all the interfaces implemented by your object that can generate rich error information. 

Once you add ISupportRichErrorInfo to your component, you can use standard error objects to give detailed information about errors that occur in your component. To do this, create the error object, initialize it with information about the error, then set it as the thread error object. To help you, ATL provides a global function called AtlSetErrorInfo(): 



ATLINLINE ATLAPI AtlSetErrorInfo(
   const CLSID& clsid, 
   LPCOLESTR lpszDesc, 
   DWORD dwHelpID,
   LPCOLESTR lpszHelpFile, 
   const IID& iid, HRESULT hRes,
   HINSTANCE hInst);

The parameters include the CLSID of the component that generated the error, the descriptive text for the error, the help file context, the name of the file, and the IID of the interface. You use these parameters to initialize the error object. hRes is the status code returned by the method that generated the error and is merely returned by AtlSetErrorInfo(). This allows you to use the function like this: 



if (sAge < 18)
   return AtlSetErrorInfo(CLSID_Obj, 
      L"This person cannot buy "
      L"alcohol in the UK", 0, NULL,
      IID_IObj, E_INVALIDARG, NULL);

The return value from the method with this code will be E_INVALIDARG. ATL provides several overloaded versions of AtlReportError() for error messages passed as strings or held as string resources. These methods simply delegate to AtlSetErrorInfo(), but because a resource ID can be passed, they need to indicate the HINSTANCE of the resource DLL. This is the purpose of the final parameter to AtlReportError(). 

If your ATL class derives from CComCoClass<>, which it should if it's externally creatable, your code will be able to use one of many overloaded versions of Error(), which simply call AtlReportError() with suitable defaults. So, you can reduce the previous code to this: 



if (sAge < 18)
   return Error(
      L"This person cannot buy "
      L"alcohol in the UK",
      IID_IObj, E_INVALIDARG);

This is fine, but you still have a problem: If your method called another method that generated the error and set an error object, that information is lost. You can get around this by checking if an error object already exists. If so, read its description and append it to your error text: 



HRESULT GenerateError(REFIID iid, 
   LPOLESTR lpSrc, LPCOLESTR lpDesc, 
   LPOLESTR lpFile, DWORD dw)
{
   CComQIPtr<IErrorInfo> pErr;
   CComBSTR bstrDesc;
   if (GetErrorInfo(0, &pErr) 
      == S_OK)
   {
      pErr->GetDescription(
         &bstrDesc);
      bstrDesc += L" "; 
      bstrDesc += lpDesc;
      pErr.Release();
   }
   else bstrDesc = lpDesc;
   CComPtr<ICreateErrorInfo> pCEI;
   CreateErrorInfo(&pCEI);
   // setting other values missed out 
      pCEI->SetDescription(
         bstrDesc.m_str);
   pErr = pCEI;
   return SetErrorInfo(0, pErr);
}

This code calls GetErrorInfo() to see if an error object has already been set. If so, it obtains the error object and appends its descriptive text to the error object you want to return. You must create a new error object because the thread's error object is read-only. Calling SetErrorInfo() releases any error object that might have already been set for the thread. Although doing this allows you to retain former error information, the returned error description has a poor format, and any client code needs to split up the various error strings to make them meaningful. 

Using Extended Error Objects 
To solve these problems, you need an error object that can hold information for more than one error. The OLE DB extended error object fits this requirement. Unlike standard error objects, you create OLE DB extended error objects using CoCreateInstanceEx(). Extended error objects also implement the IErrorRecords interface, which allows you to add ERRORINFO records (see Figure 1). You can access these records through this interface, or you can access only the first record through the IErrorInfo interface. Because extended error objects implement IErrorInfo, you can use them wherever you use a standard error object.    
Figure 1 Group Error Records. Click here.

 





Take a look at ERRORINFO: 



typedef struct tagERRORINFO {
   HRESULT   hrError;
   DWORD     dwMinor;
   CLSID     clsid;
   IID       iid;
   DISPID    dispid;
} ERRORINFO;

Can you see what's odd about this? That's right: It has no strings. Error records do not contain descriptive error information. I'll come back to this issue in a moment, but first I'll show you how to add an error record to the extended error object. You do this by calling IErrorRecords::AddErrorRecord(): 



HRESULT AddErrorRecord (
   [in] ERRORINFO* pErrorInfo,
   [in] DWORD dwLookupID,
   [in] DISPPARAMS* pdispparams,
   [in] IUnknown* punkCustomError,
   [in] DWORD dwDynamicErrorID);

Again, you'll find no descriptive string. The dwLookupID parameter identifies the error string that should be returned. This value is passed to a separate object, called a Lookup object, which implements an interface called IErrorLookup that does the work of generating a string. Notice that each error record can have parameters as well as a custom object. The parameters are passed to the Lookup object, which then can customize the error text (for example, to identify which parameter was incorrect). 

Clients get error information in two ways: They can obtain the first ERRORINFO added by accessing IErrorInfo on the object, or they can get the other records by calling IErrorRecords::GetErrorInfo() to get an error object based on the ERRORINFO: 



HRESULT GetErrorInfo( 
   [in] ULONG ulRecordNum,
   [in] LCID lcid,
   [out] IErrorInfo** ppErrorInfo);

Clearly, the first parameter is the index of the record you require, but notice the second parameter. It allows you to indicate a locale. In other words, you specify that any returned strings should be generated for a specific locale. The client returns an error object immediately. However, when the client attempts to call GetDescription() on this error object, it contacts the Lookup object and calls IErrorLookup::GetErrorDescription(): 



HRESULT GetErrorDescription( 
   [in] HRESULT hrError,
   [in] DWORD dwLookupID,
   [in] DISPPARAMS* pdispparams,
   [in] LCID lcid,
   [out] BSTR* pbstrSource,
   [out] BSTR* pbstrDescription);

The Lookup object is passed the Lookup ID and any parameters associated with the error record. In addition, the locale is passed, and the Lookup object uses this information to generate the descriptive string and the name of the object that caused the error. This information is returned back to the client, which receives it when IErrorInfo::GetDescription() returns. The client has no knowledge that the Lookup object is used. 

Accessing Extended Error Objects
Extended error objects are not immutable: Any code that can access the error object can add information to it. This means the client can access the error information set by your code, as well as any information added by any code your method called or any code that called your method. So, the client can build up a chain of error messages that indicates where the error first occurred and the effect it had on subsequent code. 

However, all the code that sets error information must understand extended error objects and check if an extended error object has already been created. If you write the entire object hierarchy, this won't be a problem, but if you use other objects that use only standard error objects, you must take this into account. 

You can add error messages to an extended error object (see Listing 1). Notice that if this code is called when a standard error object has been set for the current thread, its information is added as a record to an extended error object, with its source and descriptive strings added as parameters. I also show how to handle this in the Lookup object (see Listing 2). In this code, I show only how to handle errors that originate from a standard error object; you should add your own cases in the switch statement for custom error messages. (The example in the online code shows more complete code for a Lookup object.) 

Lookup Objects: Pros and Cons
Using Lookup objects like this offers two main advantages: The descriptive text is locale dependent, and it's generated only when needed. However, this last point is also the disadvantage of Lookup objects because if the Lookup object is on another machine, then additional�and expensive�network calls will be made. 

A Lookup object is merely a COM object, and you register it in the usual way. However, so COM knows which Lookup object it should use when a component generates an extended error object, that component needs a key called ExtendedErrors. This key is the Lookup object's CLSID and should contain subkeys for every Lookup object the extended error object uses. 

AtlDBCli.h contains code for accessing extended error objects. The global method AtlTraceErrorRecords() obtains the error object set for the current thread and dumps the contents of all error records into the debug stream. The method uses the CDBErrorInfo class to access the error object and its records. In spite of its name, you can use this class whether the error object was created by an OLE DB provider or not. As long as you have OLE DB installed, you're free to use extended error objects, even if your code does not use OLE DB. Furthermore, every Windows 2000 machine has OLE DB installed, so if you target your code to Windows 2000, rest assured it can use extended error objects. 

The sample code for this article contains two objects: File and MyLookup. The File object, a simple wrapper around the Win32 FindFirstFile() API, takes a full path to a file on the machine where File runs. This path might contain environment strings: 



%windir%\system.ini

On my machine, this string expands to C:\Winnt\system.ini. The object locates the specified file and returns its size. So, for the previous example, the object returns 238 bytes�because on NT this file is used by the 16-bit WOW subsystem, and I don't run 16-bit applications. 

If errors occur, information is put into an extended error object. The File object's code checks for several error conditions: 


NULL values for [out] parameters. This condition occurs only if the object is created in-apartment. If the object is created out-of-apartment, the marshaling layer returns the error. 
An empty string passed for the filename. 
An invalid, but nonempty, name is used. 
An invalid environment variable is used. 
The code adds more than one error record into the error object, and in the case of an invalid environment variable, it generates a standard error object to show you how it is converted to an ERRORINFO. You can run the client code on Windows 9x, NT 4.0, or Windows 2000. It calls the File object either in process or in the DllHost surrogate (Windows 9x must have DCOM installed to use this), and it calls the error object to generate the various error conditions. 

It's always a good idea to provide rich error information from your objects, but the standard error objects can prevent you from doing this. Any code can use the OLE DB extended error objects and allow you to return multiple records of error information. This gives the clients that use your code more information about how to correct a problem. 


Richard Grimes is the author of ATL COM Programmer's Reference, Professional ATL COM Programming, and Beginning ATL 3 COM Programming, all of which cover ATL 3.0. He is also author of Professional Visual C++ 6 MTS Programming. All are published by Wrox Press. Reach Richard by e-mail at atl.dev@grimes.demon.co.uk
 


c0Title: Get Started With the VC++ AppWizard
c1Code:
July 2000
 
http://www.devx.com/premier/mgznarch/vcdj/2000/07jul00/fu0007/fu0007.asp
Make your project easier to enhance and maintain by modifying AppWizard files. 

by Bill Wagner 


   This article is the first in a multipart series that will help you use Visual C++ more effectively. In the next few articles, I'll show you how to work with the ClassWizard, work with MFC, create non-MFC applications, and work with the Visual C++ Debugger. I chose to begin with AppWizard because it's the most common way to start a new application. 
What you need:
Visual C++ 6.0  
 

The Visual C++ AppWizard generates many files when it creates a new application. It also applies default project settings for compiler and linker options. Finally, it creates a set of default resources�dialogs and menus�that form the basis of your UI (user interface). In this article, I'll discuss the various files that AppWizard creates for you, show you some good changes to make to the initial project settings, and explain what each of the AppWizard generated files are for. When you're finished, you'll not only gain an understanding of the files that AppWizard creates to get you started on your new application, but you'll know how to modify these generated files so your project is easier to enhance and maintain. 

I'll begin by creating an application. When you select New from the Microsoft Visual C++ (MSVC) File menu, you get the MFC AppWizard dialog. AppWizard can create many types of new applications. I use an MFC-based application as an example in this article. MFC-based applications are standalone Windows applications. However, much of what I discuss applies to other kinds of applications as well. 

The first step is to decide what kind of application you are going to make. In this article, I'll create a multiple-document interface (MDI) application. An MDI application enables you to have more than one document open in the main window at a time. You can also choose a single-document interface (SDI) application, or a dialog-based application. There is also a checkbox for you to decide whether you want MFC's Document/View architecture support, and I've elected to have the support. 

In the Step 2 AppWizard dialog box, you're able to add optional database support to the application. For my example, I use the default of none. Step 3 enables you to add Compound Document and COM support. I use the default settings: no Compound Document or Automation support. (A compound document lets you embed ActiveX objects in the document, and automation support provides a COM interface to expose your application to automation clients through the document class. You won't need these features for this sample application.) 

By default, the new application will support ActiveX controls. Let's leave this checked for the sample application because in a later installment, you'll add ActiveX controls through the Component Gallery. 

The Step 4 dialog box (see Figure 1) has many user interface elements to select from. I usually add Context-sensitive Help, and I switch the toolbar style to Internet Explorer ReBars (ReBars are the flat style of toolbar introduced in IE4).     
Figure 1 Deciding on the User Interface Click here.

 

The Step 4 dialog box also includes settings for file extensions in file-based applications through the Advanced button. The Advanced Options dialog has two tabs: Document Template Strings and Window Styles. Under Document Template Strings, you can define what document type your application supports (see Figure 2). This dialog lets you specify the default file extension string, and if your application supports multiple document types, you can add them later.  
Figure 2 Defining Your Document Type Click here.

   

If you look at Figure 2, you'll also see the completed Document Template Strings dialog with the file extension, sample. (Yes, you can choose extensions with more than three letters now.) You don't need to change the file type ID. This type ID is how your document type is labeled in the system registry; the users will never see this string. The bottom five boxes, in the section Localized stings, are the strings your application displays. The Main frame caption represents the main title of your application; the Doc type name is displayed in the File Save dialog as the "Save as Type" box; the Filter name contains the string that's displayed in the File Open dialog for file types; the File new name (short name) contains the default name of new documents created by your application; and the File type name (long name) is used with COM Automation. 

The other tab in the Advanced Options dialog box, Window Styles, describes how your application appears. There are two options here that I often change: the MDI child frame styles and the Use split window checkbox. Setting the child frame style to Maximized starts your application the same way Microsoft Word starts, whereby the entire MDI window is taken up by one document. Leaving the child frame style unchecked gives the same appearance as VC, where each child window takes the default portion of the MDI client window. The Use split window checkbox creates a view that can be split in two parts. (MSVC uses this in the source editor and image editor windows.) 

For my example, I use all the defaults that appear in the Step 5 AppWizard dialog box. You can, however, choose to link to MFC statically, rather than as a DLL. You can also specify an Explorer-like user interface, if you prefer. In future columns, I'll show you how to work with these other application styles. 

In the Step 6 dialog box, you can change the names of the classes that AppWizard creates, or change the base classes for some of the classes (see Figure 3). Our example uses the CEditView class for the Base class. CEditView supports a simple text-editing window. 

    
Figure 3 Changing Default Base Classes Click here.

 

What AppWizard Hath Wrought
You now have the initial application. Your first instinct is probably to build the application and see what you have. Before you do that, however, add the entire project to your source control system. Doing so will help when you receive feature requests later in the development cycle. 

Although a lot of options were manipulated in AppWizard for this example, only a few of them are easily modified later. Sometimes, the best way to determine how to add support for a feature is to make a new application with the different set of features and figure out what changed. Using your source control system makes this easy. You can check out the initial versions of every file in the project. Then, you use AppWizard to create the new version of the initial project. Your source control system can tell you what changed in each of the project's files, and you can make the corresponding changes to the current version of the project files. Depending on your source control system, it might even perform the merges for you. 

Some of the files AppWizard writes shouldn't be added to your source control system; they're always generated when needed. These files should not be checked in: sample1.aps, sample1.clw, sample1.ncb, sample1.opt, and sample1.dsw. The DSW file is the workspace file. It contains the list of projects, the list of open windows, and the current editing location in each window of your editing session. The NCB file contains the class browser information. This information provides the input for the Class View tab in VC's project window. The CLW file contains ClassWizard information. It can be regenerated when needed. And the other files I've mentioned are intermediate files that VC uses for speeding up builds. 

Although I always modify some of the project settings that AppWizard generates, the defaults are reasonable for most projects. However, for large projects, I like to modify the options because I believe it produces a better executable. My goal is to produce the fastest, smallest executable possible in release builds. Also, I want to do the most to minimize the build times for debug builds. Finally, the C++ compiler can help find many common coding errors if you let it. Although these changes aren't absolutely necessary, I've found they pay huge dividends on large multideveloper projects. 

On the C/C++ page General category, I always select Warning (level 4) for both release builds and debug builds. For larger projects, I change the release build optimizations from Maximize Speed to Minimize Size. The debug info selection should be Program Database for Edit and Continue. 

There are two settings on the C++ language page that might need tweaking. The Enable Exception Handling and Enable Run-Time Type Information (RTTI) both enable C++ language features that can have a negative impact on an application's performance. Exception handling adds code to every function in your application to support stack unwinding when exceptions are thrown and caught. Enabling RTTI adds code to support the dynamic_cast operators, the C++ typeid operator, and similar functions. I turn both operators off when I first make an MFC project. These are the same defaults the ATL AppWizard uses. With Warning (level 4) set, if you write code that uses these language features, the compiler will warn you. At that time, you can turn the related option on. However, there's no need to pay for the feature until you need it. 

There is one setting in the Code Generation category that people often misunderstand. The target processor defaults to Blend. This setting means that the compiler generates machine code for the most common processor currently in the market. VC6 generates code that's optimized for the Pentium when the Blend option is set. By leaving this setting alone, newer versions of the compiler will tune the machine code for newer processors automatically. 

I always enable the Incremental Compilation checkbox in the Customize category during debug builds. This speeds up debug builds during the debug cycle. The rest of the defaults are fine. 

Finally, there is one option I change on the Link options page. I add the /opt:ref option to the linker settings for the release build. /opt:ref causes the linker to remove unreferenced functions from the executable. When this is combined with the compiler option for Enable function-level linking, you can get a fairly small executable. A user element to set this option does not exist. You need to type it into the Project Options textbox on the Link tab's General category (see Figure 4). Add this option only for the release builds. It's incompatible with the incremental linking option that's better for debug builds.   
Figure 4 Modifying the Linker Options Click here.   

Handling Warning (Level 4)
As I said previously, I always use Warning (level 4). However, this warning level gets quite picky about C++ coding style. Also, some Warning (level 4) messages are compiler information messages. So, I make some modifications to stdafx.h to stop the compiler messages that aren't indicative of coding errors. The warning #pragma gives you complete control over whether individual warning messages are generated. I've included my version of stdafx.h with this article (see Listing 1). The first section disables warnings that aren't the result of possible coding errors. 

Header files that don't compile cleanly at Warning (level 4) do exist. I make some other modifications to stdafx.h to minimize the warnings from the standard header files. The push #pragma temporarily lowers the warning level while the header files are being processed. The pop #pragma restores the warning level to its previous level. 

After all this work on project settings, it's time to build and run the application. The context-sensitive help is on in this sample. There is one long-standing problem with the help compiler and most project settings. The help compiler has no way to specify an include path. Therefore, the HPJ file contains the full path to a help map file in the version that AppWizard generated. This will not build on your machine if you have installed VC in a different directory than I have. To fix this problem, you have to edit the sample1.hpj file in the HLP directory. Replace the line: 

#include<C:\MSVS\VC98\MFC\
     include\afxhelp.hm>
with the correct path for your VC installation. 
Although the method you learned in this article requires you spend some time on the project settings to make the application easier to maintain, you do not have to add any code beyond what AppWizard writes for you. AppWizard saves you the drudgery of recreating the same boilerplate code every time. The modifications and steps made here make it easier to maintain your growing application as you add more features to it. The changes in the project settings make it easier to spot any coding errors you might make later. Finally, the changes to stdafx.h make it easier to spot any coding errors you introduced. 

Next month, I will show you how to use the Component Gallery and the ClassWizard to enhance your application, and will work with the toolbars, dialogs, and menu bars. 

Bill Wagner is the president/software architect for Midwest Seas Software Development Inc. Bill has several years of experience in Windows and C++ programming. He specializes in C++, Java, and COM-based enterprise-programming solutions. He has taught several classes for developers using C++, Visual C++ tools, and MFC. You can reach him by e-mail at wwagner@midwestseas.com
 


c0Title:
How do you create a component that has a PublicNotCreatable value with Visual C++ instead of Visual Basic? 

c1Code:
In Visual Basic, setting the Instancing property of a class module to PublicNotCreatable at design time affects the binaries in two ways: The first is that the class will achieve visibility from the extern (by comparison, private Visual Basic classes are confined within the VB module only and do not exist outside). The second is that external clients are not allowed to create concrete instances of the class; its footprint is available for everyone to see, but nobody can construct a new shoe from its shape. 

The Visual Basic virtual machine acts as a middle layer between the high-level programmer and the low-level COM machinery, so accomplishing a similar behavior in Visual C++ requires doing by hand what the Visual Basic runtime does implicitly. 

With Visual C++ you have to explicitly tell the world about the coclasses you export, so there is nothing special to perform to duplicate the "public" property of VB: just publish the prototype of the implemented interfaces in IDL and/or in the form of a type library, and distribute them to your clients. 

To restrict your clients to only manipulating the instances and not creating new ones, you can intervene at one of two stages. Under normal circumstances, the client will issue the instantiation of a coclass for which it knows the CLSID by means of the CoCreateInstance[Ex]() API, or an ATL creator that works equivalently. Internally this API browses the HKEY_CLASSES_ROOT\CLSID registry key to find the complete path of the module in charge of managing that coclass, and loads it into memory. Subsequently, the API invokes the well-known export DllGetClassObject() in the DLL and retrieves an interface pointer (typically IClassFactory*) to the class object associated with the desired CLSID. 

To prevent the creation of new instances you can intervene either at the registration level (don't associate the CLSID to its module in the registry) or at the class object level. Your mileage may vary, but operating at the registration level carries numerous advantages, since your server's code remains oblivious to the restriction, particularly if you rely on the assistance of a framework capable of implementing class factories mechanically (ATL falls into this category). You also avoid disturbing the semantics of DllGetClassObject() and IClassFactory by pretending to be able to perform something (coclass instantiation) that you know you are going to prohibit

 
Davide Marcato is a freelance international consultant, writer and speaker specializing in Windows, Java and COM/MTS/COM+ development and system design. He is a member of the instructional staff at DevelopMentor and an independent consultant managing projects of all sizes. A Windows DNA expert and a Microsoft certified developer, Davide is also a prolific technical writer and conference speaker worldwide, regularly contributing to several magazines such as Visual C++ Developers Journal, Dr. Dobb's Journal, MIND and COM Developer. For VCDJ he serves as a technical editor and Q&A columnist, and sits in the editorial advisory board of both MSDN Journal and VCDJ. Contact him through his Web site at http://www.DavideMarcato.com or by email at marcato@programmers.net.


c0Title: Hybrid Sort Algorithm and article on sorting
c1Code:
http://eternallyconfuzzled.com/tuts/sorting.html

We'll use quicksort until it's obvious that we're nearing a degenerate case. We can test for that by figuring out the depth of recursion that qualifies as O(log N). When we get to that depth, we're starting to leave the boundaries of quicksort's average case. Once we hit that cutoff, we then switch to heap sort because it's guaranteed to be O(Nlog N). By doing this, we never leave a complexity of O(Nlog N). We can also implement all of the optimizations for quicksort such as the threshold and insertion sort at the end, as well as already sorted subarrays. The resulting algorithm is called introsort, short for introspective sort because it's smart enough to change how it works when things start to get hairy:

void jsw_introsort ( int a[], int n )
{
  jsw_introsort_r ( a, 0, n - 1, (int)( 2 * log ( n ) ) );
  jsw_insertion ( a, n );
}


void jsw_introsort_r ( int a[], int first, int last, int depth )
{
  while ( last - first > THRESHOLD ) {
    if ( depth == 0 )
      jsw_heapsort ( &a[first], last - first + 1 );
    else {
      int pivot;

      if ( is_sorted ( a, first, last ) )
        return;
   
      pivot = jsw_partition ( a, first, last );
      jsw_introsort_r ( a, pivot + 1, last, depth - 1 );
      last = pivot - 1;
    }
  }
}


int jsw_partition ( int a[], int first, int last )
{
  int pivot, mid = ( first + last ) / 2;

  /* Largest of two */
  pivot = a[first] > a[mid] ? first : mid;

  /* Smallest of remaining */
  if ( a[pivot] > a[last] )
    pivot = last;

  jsw_swap ( &a[pivot], &a[first] );
  pivot = first;

  while ( first < last ) {
    if ( a[first] <= a[last] )
      jsw_swap ( &a[pivot++], &a[first] );

    ++first;
  }

  jsw_swap ( &a[pivot], &a[last] );

  return pivot;
}


void jsw_heapsort ( int a[], int n )
{
  int i = n / 2;

  while ( i-- > 0 )
    jsw_do_heap ( a, i, n );

  while ( --n > 0 ) {
    jsw_swap ( &a[0], &a[n] );
    jsw_do_heap ( a, 0, n );
  }
}


void jsw_do_heap ( int a[], int i, int n )
{
  int k = i * 2 + 1;
  int save = a[i];

  while ( k < n ) {
    if ( k + 1 < n && a[k] < a[k + 1] )
      ++k;

    if ( save >= a[k] )
      break;

    a[i] = a[k];
    i = k;
    k = i * 2 + 1;
  }

  a[i] = save;
}


void jsw_insertion ( int a[], int n )
{
  int i;

  for ( i = 1; i < n; i++ ) {
    int j, save = a[i];

    for ( j = i; j >= 1 && a[j - 1] > save; j-- )
      a[j] = a[j - 1];

    a[j] = save;
  }
}


void jsw_swap ( int *a, int *b )
{
  int c = *a;
  *a = *b;
  *b = c;
}


int is_sorted ( int a[], int n )
{
  int i;

  for ( i = 0; i < n - 1; i++ ) {
    if ( a[i] > a[i + 1] )
      return 0;
  }

  return 1;
}





Here's the entire article:

 

 

I'm confident that you already know what sorting is. Not only is it a concept that saturates computer science, it's also pretty intuitive. Basically you take things that are out of order, and put them into order. Examples of sorting are a phone book being ordered by name, or a coin machine that puts the same type of coins into those neat little packages so that the bank will give you paper money in exchange. :-) The idea behind sorting is simple. It makes life easier if things are in order, not the least important is finding things. It'd be a nightmare to try and find somebody's phone number if the phone book wasn't ordered by name.

Beyond the practical uses for sorting, the algorithms are fundamental to computer science, and fluency in the techniques used by sorting algorithms provides insight into the craft of programming in many unexpected areas. Sorting also gives one a certain measure of confidence in designing and analyzing algorithms because most of the techniques used appear in the context of sorting as well.

Finally, it has been said that computers have spent more time sorting data than anything else, so it makes sense to have a strong background in the concept and theory of sorting, as well as a firm understanding of the different sorting methods and their relative strengths and weaknesses. Since sorting efficiently is surprisingly complicated, programmers should try to avoid adding to the time wasted by using a poor algorithm for the job.

Many generic sorting libraries already exist and are ready to be used, such as C's qsort, or C++'s std::sort or std::partial_sort. However, these general algorithms are not always the best option. Yes, they should be first on your list of possible solutions because you're basically given a tested and debugged algorithm that's easy to use. That's far superior to writing your own algorithm, testing it, and debugging it before it can be used with any confidence.

However, there are two distinct problems with the standard library sorting algorithms. First, they're designed to work for as many cases as possible, and may not be practical or efficient for your needs. For example, if qsort is too slow, how to do you fix the problem? You can find another library, but what are the chances that it's any better than qsort? What if you need a sorting algorithm that's tailored to your data? The chances of finding a library that meets your needs are slim indeed unless your needs are very common.

Second, libraries are generally designed as black boxes, so users of the functions are have no idea what algorithm is actually being used. This isn't as much of a problem in the standard C++ library, where the sorting algorithms have well defined performance attributes that must be met, but many people are surprised to learn that qsort may actually be implemented as anything as long as it eventually sorts the array correctly. The name suggests the quicksort algorithm, but in reality it could be bubble sort, or worse, a very poor implementation of quicksort that works for many cases but runs very very slow in common worst cases. 

As such, it's beneficial to understand what algorithms are available, what their advantages and disadvantages are, and how to implement your own algorithm that's custom tailored to your data if the need arises. And you can brag that you know half a dozen sorting algorithms and sneer at your friends who can barely write bubble sort off the top of their heads. Bragging rights are a pretty darned good reason to learn something in my opinion. ;-)

Table of Contents
Sorting Considerations 
Preliminaries 
Selection Sort 
Heap Sort 
Insertion Sort 
Shell Sort 
Bubble Sort 
Quicksort 
Merge Sort 
Radix Sort 
Conclusion 
Sorting Considerations
To sort or not to sort. That's the question, isn't it? Sorting an unordered array or list is time consuming, even if you do it efficiently, so it makes sense to avoid sorting when you can. That usually amounts to using a better data structure such as a hash table (where sorting probably isn't necessary), or a binary search tree (where items are sorted by default). Sometimes you don't even need to sort! It could be just as fast, or faster, to just brute force your way through things. It really isn't noticeably slower to use a sequential search on an array of about 50 items than it is to sort the same array and then use a binary search on it. To use a crude analogy, it doesn't take a wrecking ball to destroy a sand castle.

Okay, let's pretend that we want to sort. What about stability? Stability, you say? What's stability? No, it's not a part of my psychological diagnosis that's immediately preceeded by �lack of�. Stability is what happens when two items compare as equal when sorting. There are two kinds of sorting algorithms concerning stability, stable and unstable (obviously!). The only difference is how they treat duplicate items.

In a stable algorithm, two items that compare as equal will retain their original relation to each other as in the original unsorted array or list. This makes absolutely no difference if the items being compared consist only of, say, integral values. When 2 compares equal to 2, it really doesn't matter which 2 is placed before the other in the final sorted sequence. However, consider the more common situation where items consist of more than one value, and only one of those values is used as the item for sorting:

 |(5:4)|(6:6)|(3:1)|(5:5)|(1:0)|(3:2)|(4:3)|(6:7)|

When sorting on the first half of the item, a stable sort has to give a result that retains the original order of the second half of the item. In other words, the second values have to be in sorted ascending order after the sort is finished, or the algorithm isn't stable:

 |(1:0)|(3:1)|(3:2)|(4:3)|(5:4)|(5:5)|(6:6)|(6:7)|

An unstable sort has no such restriction. Of the algorithms that we'll cover in this tutorial, the following are naturally stable, but the others can be made stable at the cost of using more space or taking more time. For example, selection sort is not usually stable, but can easily be made so by inserting the new item (shifting all items after its location to make a hole, like insertion sort) instead of simply swapping items:

Selection sort is stable if you shift instead of swap.
Insertion sort is stable.
Bubble sort is stable.
Counting sort is stable.
Merge sort is stable if the merge algorithm is stable.
LSD radix sort must be stable to work correctly.
MSD radix sort is stable if the underlying sort is stable.

What about performance? This is a tricky area because sorting algorithms are all across the board. The performance complexities you'll see primarily are O(N2), O(Nlog N), and O(N). It should be relatively obvious that the upper bound for any sorting algorithm is infinite as long as it manages to sort the items eventually. Naturally, this suggests a realistic upper bound of O(N!), because sorting can be thought of as picking a sorted permutation of the items. However, the canonical awful algorithm, called bogosort, is probably the worst possible sorting algorithm. Bogosort is equivalent to throwing a deck of cards in the air, then testing to see if they're sorted when you pick them up at random. Bogosort could potentially never end due to the its random nature.

Lower bounds aren't as obvious. The lowest possible bound for most sorting algorithms is O(Nlog N). This is because most sorting algorithms use item comparisons to determine the relative order of items. Any algorithm that sorts by comparison will have a minimum lower bound of O(Nlog N) because a comparison tree is used to select a permutation that's sorted. A comparison tree for the three numbers 1,2, and 3 can be easily constructed:

                             1 < 2

               1 < 3                       1 < 3

       2 < 3           3,1,2       2,1,3           2 < 3

  1,2,3     1,3,2                            2,3,1     3,2,1

Notice how every item is compared with every other item, and that each path results in a valid permutation of the three items. The height of the tree determines the lower bound of the sorting algorithm. Because there must be as many leaves as there are permutations for the algorithm to be correct, the smallest possible height of the comparison tree is logn!, which is equivalent to O(Nlog N).

So are we doomed to O(Nlog N) as the best possible performance for sorting algorithms? Well, yes, if you use item comparisons to determine relative order. Therefore, the most general of sorting algorithms will be limited by this lower bound. However, it's possible to meet the safe lower bound of O(N) for sorting. We'll look at some of these algorithms later when we look at the counting and radix sorts.

It's easy to see that O(N) is a safe lower bound on general sorting algorithms for the obvious reasons; you can't sort what you haven't seen. Well, technically, you could rely on the law of quantum indeterminacy whereby not observing any of the items, you place them in a state of superposition and it's both sorted and unsorted, and the sorting process would be O(1). But as of yet, nobody has suggested a practical use for such a sorting algorithm, or even whether it would work correctly in anything but a theoretical sense. :-)

Preliminaries
Before we start, there are a few helper functions that I'll be using in much of the code. Rather than keep repeating myself, I'll supply it all here. The first is a swap function that takes pointers to two items and swaps the items:

void jsw_swap ( int *a, int *b )
{
  int c = *a;
  *a = *b;
  *b = c;
}

Next, it's useful to be able to quickly determine if an array is already sorted or not for testing, and we'll use it as an optimization feature later, so here is a function that returns 1 if the array is sorted and 0 if it isn't:

int is_sorted ( int a[], int n )
{
  int i;

  for ( i = 0; i < n - 1; i++ ) {
    if ( a[i] > a[i + 1] )
      return 0;
  }

  return 1;
}

Finally, some of the algorithms work with linked lists. To save you the trouble of figuring out what I mean, here's the node and list structure that I built the lists with:

struct jsw_node {
  int data;
  struct jsw_node *next;
};

struct jsw_list {
  struct jsw_node *head;
  int size;
};

Selection Sort
One of the two most obvious ways to sort data is to find the largest (or smallest) item in the collection, and then move it to the back. This straight selection process is repeated for all other items in the list except for the last of them, then again for all items except for the last two, and so on until all items are ignored. When all items are ignored, they are all in their sorted position, and the algorithm is complete. An example of this simple process follows:

 |41|67|34|00|69|24|78|58|62|64<
 |41|67|34|00|69|24|64|58|62<78|
 |41|67|34|00|62|24|64|58<69|78|
 |41|58|34|00|62|24|64<67|69|78|
 |41|58|34|00|62|24<64|67|69|78|
 |41|58|34|00|24<62|64|67|69|78|
 |41|24|34|00<58|62|64|67|69|78|
 |00|24|34<41|58|62|64|67|69|78|
 |00|24<34|41|58|62|64|67|69|78|
 |00<24|34|41|58|62|64|67|69|78|
 <00|24|34|41|58|62|64|67|69|78|

The code to do this is as simple as finding the largest item in the array. A few notes should be made though. If the largest item is the current end of the array, no swap needs to be done, so we use a conditional test to avoid a function call and the operations of swapping an item with itself. This algorithm looks at every item in the array to find the largest. It has to, because no other order has been imposed on the array to make selection easier, so it's slow:

void jsw_selection ( int a[], int n )
{
  while ( --n > 0 ) {
    int i, max = n;

    for ( i = 0; i < n; i++ ) {
      if ( a[i] > a[max] )
        max = i;
    }

    if ( max != n )
      jsw_swap ( &a[n], &a[max] );
  }
}

There are a few important little factoids about straight selection sort that you need to remember. First, all of the items have to be present before the sort can begin. That means that selection sort isn't a viable solution for sorting items as they come though an input stream or a random number generator. The array has to be completely filled before you can sort it. Second, straight selection sort is slow because the process of selection is slow. Since straight selection is an O(N) operation, and the algorithm does it approximately N times, straight selection sort is a quadratic sorting algorithm. Quadratic sorts are the slowest practical algorithms you'll see in the real world. Finally, selection sort is very efficient in terms of data movement. If comparisons are significantly cheaper than swaps, selection sort performs well.

As presented above, the straight selection sort is not stable. That is, if the items have more data attached to them that aren't a part of the comparison, the relative order of duplicate items is unspecified by the algorithm. To make the sort stable such that duplicate items retain their relative order, we can select the last of any duplicates and shift instead of swap Of course, this removes the primary benefit of selection sort, lack of data movement, because we're moving items around in the shift:

void jsw_selection ( int a[], int n )
{
  while ( --n > 0 ) {
    int i, max = n;

    for ( i = 0; i < n; i++ ) {
      if ( a[i] >= a[max] )
        max = i;
    }

    if ( max != n ) {
      int save = a[max];

      for ( i = max; i < n; i++ )
        a[i] = a[i + 1];

      a[n] = save;
    }
  }
}

Let's look at how that works with a quick trace by adding some extra data to each item and throwing in a few duplicates. Notice how the secondary numbers are in the same order after the sort as before the sort. For example, 69,4 is in front of 69,5 both before and after the algorithm touches them:

 |41,0|41,1|34,2|00,3|69,4|69,5|78,6|78,7|62,8|64,9<
 |41,0|41,1|34,2|00,3|69,4|69,5|78,6|62,8|64,9<78,7|
 |41,0|41,1|34,2|00,3|69,4|69,5|62,8|64,9<78,6|78,7|
 |41,0|41,1|34,2|00,3|69,4|62,8|64,9<69,5|78,6|78,7|
 |41,0|41,1|34,2|00,3|62,8|64,9<69,4|69,5|78,6|78,7|
 |41,0|41,1|34,2|00,3|62,8<64,9|69,4|69,5|78,6|78,7|
 |41,0|41,1|34,2|00,3<62,8|64,9|69,4|69,5|78,6|78,7|
 |41,0|34,2|00,3<41,1|62,8|64,9|69,4|69,5|78,6|78,7|
 |34,2|00,3<41,0|41,1|62,8|64,9|69,4|69,5|78,6|78,7|
 |00,3<34,2|41,0|41,1|62,8|64,9|69,4|69,5|78,6|78,7|
 <00,3|34,2|41,0|41,1|62,8|64,9|69,4|69,5|78,6|78,7|

Heap Sort
The straight selection sort is probably the simplest sorting algorithm, but that simplicity is really the only benefit. Selection sort has quadratic time complexity, which is the worst complexity of the practical sorting algorithms that you'll see in the real world. There are a handful of quadratic sorting algorithms in common use, and while selection sort isn't the worst of them, you're really comparing the lowest common denominators with each other. Maybe we should work smarter instead of trying to pick the best of the worst. ;-)

The very name of selection sort suggests a way to improve the algorithm. Since the biggest problem with selection sort is the linear time it takes to select the largest item, we can find the most improvement by solving the selection problem more efficiently. In real code, we would do that with a priority queue, where items are ordered so that extracting the largest item is quick and easy. The code to do that if we assume an existing priority queue library is simplicity itself:

void jsw_selection ( int a[], int n )
{
  pqueue pq;
  int i;

  for ( i = 0; i < n; i++ )
    pq_insert ( pq, a[i] );

  while ( !pq_empty ( pq ) )
    a[--n] = pq_max ( pq );
}

Okay, but what if that nifty little library doesn't already exist? Well, we need to do it manually. The best known priority queue implementation is implemented with a max heap. The heap data structure has two very simple rules. It's a complete binary tree where the children of a node cannot be larger (or smaller if you want a min heap) than their parent. If you have a valid max heap then the largest item is the root of the tree. This structure can be easily converted into an array because the tree is complete, so there are no gaps:

 |962|500|724|467|464|334|478|358|41|169|

 is equivalent to

                           962

                    /              \

                500                   724

           /           \            /     \

       467               464    334         478

     /     \           /

 358         41    169

By converting an array into a heap structure, we can then easily extract the largest item from index 0. After doing that, the heap needs to be fixed so that it's still a valid heap again, and the process is repeated. This method of sorting is called heap sort, and it's one of the faster sorting algorithms with a worst case that has the same time complexity as the average case! By working smarter with the selection problem, we've turned one of the worst sorting algorithms into one of the best. Not bad, eh? :-)

Cool, so how do we do all of that junk? Well, naturally we need to figure out how to force an array to have the heap property. Basically, we can say that for each index i, the child nodes are at i * 2 + 1 and i * 2 + 2. In the above tree, we can see that 467 is a child of 500. In the array, 500 is at index 1 and 1 * 2 + 1 is index 3, which is where 467 is in the array. Try this with any of the indices and you'll see that this property holds for all of them. Also notice that the nodes with children are roughly the first half of the array and the nodes without children are the last half. So to build a heap, all we need to do is force the heap property from the lowest nodes to the root. Let's look at an example:

 |1|67|34|0|69|24|78|58|62|64|


                         1

                 /              \

              67                  34

         /          \           /    \

       0              69     24        78

     /   \          /

 58        62    64

To build a heap out of this array (I'll also include a tree representation to make things more obvious), we need to work with subtrees first. We start with 69 and its one child. Since 64 is smaller than 69, the heap property holds. Then we move to 0 and its children. 62 is the largest of the three, so we swap 62 and 0. Note that the relative order of the children is irrelevant:

 |1|67|34|62|69|24|78|58|0|64|


                         1

                 /              \

              67                  34

         /          \           /    \

       62             69     24        78

     /    \         /

 58         0    64

Now we move up a level and all the way to the right. In the array we're just decrementing the parent index though. At 34, we test the 3 nodes and find that 78 is the largest. So we swap 78 and 34 to restore the heap property:

 |1|67|78|62|69|24|34|58|0|64|


                         1

                 /              \

              67                  78

         /          \           /    \

       62             69     24        34

     /    \         /

 58         0    64

Now we go left to 69 and its two children. Since 69 is the greatest of the children and is greater than 67, we swap 67 and 69:

 |1|69|78|62|67|24|34|58|0|64|


                         1

                 /              \

              69                  78

         /          \           /    \

       62             67     24        34

     /    \         /

 58         0    64

Finally, at the root of the tree, testing 1 and its children we find that 78 is greater than both 1 and 69, so we make 78 the new root of the tree. Uh oh, this isn't a valid heap though. 78 is greater than 1, but 1 isn't greater than either 24 or 34, so we've got a problem. It appears that we can't just do local changes to a parent and its two children, we need to push the parent down as long as it violates the heap property. We can do this because we build a heap from the bottom up, so the lower subtrees are always valid heaps unless a change higher up the tree violates it. Let's do the final step by fixing 78's right subtree:

 |1|69|78|62|67|24|34|58|0|64|


                        78

                 /             \

              69                 34

         /          \          /    \

       62             67    24        1

     /    \         /

 58         0    64

Now we have a valid heap! Let's write a jsw_do_heap function that walks down the tree, making sure that the heap property is met. This is a fairly obvious method. The outer loop of jsw_do_heap handles cases where multiple parents need to be fixed down the tree. The first step inside the loop finds the largest child, the second step swaps the largest child and the parent if the child is larger. Notice how the i * 2 + 1 trick is used to find the first child. jsw_heapsort is just a translation of the priority queue pseudocode:

void jsw_do_heap ( int a[], int i, int n )
{
  int k = i * 2 + 1;

  while ( k < n ) {
    if ( k + 1 < n && a[k] < a[k + 1] )
      ++k;

    if ( a[i] < a[k] )
      jsw_swap ( &a[i], &a[k] );

    k = ++i * 2 + 1;
  }
}

void jsw_heapsort ( int a[], int n )
{
  int i = n / 2;

  while ( i-- > 0 )
    jsw_do_heap ( a, i, n );

  while ( --n > 0 ) {
    jsw_swap ( &a[0], &a[n] );
    jsw_do_heap ( a, 0, n );
  }
}

This is a surprisingly simple algorithm for how good heap sort is supposed to be, but it's not very fast, and we can do much better with only minor changes to jsw_do_heap. The current algorithm walks down every node in the tree until the end of the array. That means we're doing a lot of unnecessary work if only one push down is required in an array of 1,000,000 items. We also don't need to call jsw_swap in the loop. We can simply save the first root that we're pushing down, move children into its place, and after the loop is finished, put that saved node into its final resting place:

void jsw_do_heap ( int a[], int i, int n )
{
  int k = i * 2 + 1;
  int save = a[i];

  while ( k < n ) {
    if ( k + 1 < n && a[k] < a[k + 1] )
      ++k;

    if ( save >= a[k] )
      break;

    a[i] = a[k];
    k = ++i * 2 + 1;
  }

  a[i] = save;
}

That's much faster than our last attempt, but because we're only incrementing i by 1 each time, we're basically fixing the entire heap when we only need to fix the subtree that we swapped with, not both subtrees. So by making the simple change of setting i to k instead of incrementing it, we improve the speed of the algorithm by several orders of magnitude. jsw_heapsort doesn't change throughout all of these improvements, and we come to the final (and fastest) incarnation of heapsort for this tutorial:

void jsw_do_heap ( int a[], int i, int n )
{
  int k = i * 2 + 1;
  int save = a[i];

  while ( k < n ) {
    if ( k + 1 < n && a[k] < a[k + 1] )
      ++k;

    if ( save >= a[k] )
      break;

    a[i] = a[k];
    i = k;
    k = i * 2 + 1;
  }

  a[i] = save;
}

Okay, I'm a liar. :-) We'll look at another alternative before moving on. A lot of people are surprised to learn that heap sort can be implemented any number of ways. The heap property is a very flexible rule when it comes to how you want to enforce it, so there can be a lot of variation in how heap sort is implemented. The best way to find alternative implementations is to think about how heaps work and look for patterns. One pattern in particular that we will look at is the relationship between each index and its child indices. If you think about the simple calculation for finding a child, you'll come up with the following pattern: 

 |41|67|34|0|69|24|78|58|62|64|
 |41|67|34|
    |67|  |0|69|
       |34|    |24|78|
          |0|        |58|62|
            |69|           |64|

This shows the parents and their direct children. You can verify that the right children go with the right parents by using the i * 2 + 1 trick. 41 is index 0, 0 * 2 + 1 is 1 and 0 * 2 + 2 is 2. Okay, that's an easy one, how about the last parent and child? 69 is index 4, 4 * 2 + 1 is 9, which is the index for 64. So we know that the pattern matches what we were doing by finding k with i * 2 + 1. But since the parent index increments by 1 each time and the index of the first child increments by 2, we can work directly with the pattern by using two indices (once again, jsw_heapsort remains unchanged):

#define jmax(p,q) ( *(p) > *(q) ? (p) : (q) )
#define maxof3(p,q,r) jmax ( (p), jmax ( (q), (r) ) )

void jsw_do_heap ( int a[], int i, int n )
{
  int k;

  for ( k = i + 1; k < n; i++, k += 2 ) {
    if ( k == n - 1 ) {
      if ( a[k] > a[i] )
        jsw_swap ( &a[i], &a[k] );
    }
    else
      jsw_swap ( &a[i], maxof3 ( &a[i], &a[k], &a[k + 1] ) );
  }
}

But this is really two steps backward since it's even slower than our first attempt at heapsort, and implementing the same optimizations that we used before would make the code much more complicated, so this is really a substandard solution even though it's intellectually interesting to play around with alternatives. :-) I like to think that if you understand the variations we've looked at, you'll have a good feel for heap sort.

One problem that heap sort has (though you won't see it here) is that the traditional algorithm assumes 1-based array indices, while C uses 0-based arrays. That's proven to be a very frustrating problem because getting a 1-based algorithm to work with 0-based arrays can be tricky. As such, you'll probably see different tricks that avoid the issue, like ignoring the 0th index, or shifting the array so that the 0th index actually refers to one element in front of the array. The former is awkward and the latter is undefined by C. Other attempts are just wrong in subtle ways, and while they may seem to work most of the time, they'll break, usually at the worst possible time. ;-) No worries here though, all of my implementations are written specifically with 0-based arrays in mind. You're welcome.

Insertion Sort
The other most obvious way to sort a collection of items is by insertion. Insertion takes each new item, then locates the current ordered position in the collection and inserts the item there. The common example is sorting a bridge hand, but I don't play bridge and I don't know anyone that does, so an execution trace on our list of numbers as an example would fare better:

  1)  |41|
  2)  |41|67|
  3)  |34|41|67|
  4)  |00|34|41|67|
  5)  |00|34|41|67|69|
  6)  |00|24|34|41|67|69|
  7)  |00|24|34|41|67|69|78|
  8)  |00|24|34|41|58|67|69|78|
  9)  |00|24|34|41|58|62|67|69|78|
 10)  |00|24|34|41|58|62|64|67|69|78|

Each new item is moved into the correct position as it arrives. Unlike sorting by selection, this suggests that sorting by insertion is well suited to sorting an unknown number of items, and that the items don't need to be present before sorting can begin. So acquiring items through a stream or a generator is perfectly acceptable when sorting by insertion.

However, that very sequential nature suggests that sorting by insertion has potential performance issues when used with arrays. Insertion into the middle of an array requires that a hole be created by shifting all items after the hole to the right. For a large array, that can be incredibly slow and expensive. On the other hand, sorting by insertion into a linked list can be far more efficient in theory because the shifting step is not required.

Note that sorting by insertion can be done in-place without using any extra memory. Using insertion sort on an existing array of items would result in the following execution:

  1)  |41>67|34|00|69|24|78|58|62|64|
  2)  |41|67>34|00|69|24|78|58|62|64|
  3)  |34|41|67>00|69|24|78|58|62|64|
  4)  |00|34|41|67>69|24|78|58|62|64|
  5)  |00|34|41|67|69>24|78|58|62|64|
  6)  |00|24|34|41|67|69>78|58|62|64|
  7)  |00|24|34|41|67|69|78>58|62|64|
  8)  |00|24|34|41|58|67|69|78>62|64|
  9)  |00|24|34|41|58|62|67|69|78>64|
 10)  |00|24|34|41|58|62|64|67|69|78|

The code to do this is pretty simple. All we need to do is pick each item in the array, then make a hole where it needs to go and insert it. In fact, insertion sort is considered to be one of the simplest sorting algorithms both in concept and in implementation:

void jsw_insertion ( int a[], int n )
{
  int i;

  for ( i = 1; i < n; i++ ) {
    int j, save = a[i];

    for ( j = i; j >= 1 && a[j - 1] > save; j-- )
      a[j] = a[j - 1];

    a[j] = save;
  }
}

Unfortunately, being one of the simplest sorting algorithms also means that insertion sort is also one of the least efficient. It's in the class of sorting algorithms that have quadratic time complexity, which means that it doesn't scale well to large arrays. However, insertion sort has one really awesome feature that makes it useful as a part of more sophisticated algorithms: insertion sort is blazing fast on arrays that are sorted or almost sorted. This makes it ideal for finishing up a partial quicksort, which we'll see shortly.

Insertion sort on a linked list is almost as simple as insertion sort on an array. With linked lists we may not be able to go backward, but that's hardly a stumbling block since we can easily save the sorted items in a temporary list by extracting the nodes from the original list, inserting them into the temporary list, then pointing the original list pointer back to the temporary list before returning. The temporary list only has the overhead of an extra variable, so it's space efficient:

void jsw_insertion ( struct jsw_list *list )
{
  struct jsw_node result = {0};
  struct jsw_node *i, *step, *next;

  for ( step = list->head; step != NULL; step = next ) {
    next = step->next;

    for ( i = &result; i->next != NULL; i = i->next ) {
      if ( i->next->data > step->data )
        break;
    }

    step->next = i->next;
    i->next = step;
  }

  list->head = result.next;
}

Shell Sort
While straight insertion is particularly efficient on already sorted or almost sorted arrays or lists, it's still a quadratic sort because the overall result only sorts the items by one position at a time. Now, while this may sound like a given, it's possible to force the algorithm to move items over wider ranges by dividing the array into multiple interleaved groups. For example, dividing the insertion sort example into two groups of five, then sorting each corresponding value in those groups, then combining the groups and sorting the one group results in the following execution:

  1)  |41|67|34|00|69|   |24|78|58|62|64|
  2)  |24|67|34|00|69|   |41|78|58|62|64|
  3)  |24|67|34|00|69|   |41|78|58|62|64|
  4)  |24|67|34|00|69|   |41|78|58|62|64|
  5)  |24|67|34|00|64|   |41|78|58|62|69|
  6)  |00|24|67|34|64|41|78|58|62|69|
  7)  |00|24|34|64|67|41|78|58|62|69|
  8)  |00|24|34|41|64|67|78|58|62|69|
  9)  |00|24|34|41|58|64|67|78|62|69|
 10)  |00|24|34|41|58|62|64|67|78|69|
 11)  |00|24|34|41|58|62|64|67|69|78|

Hmm, not much better, is it? How about we divide the array into four groups instead of two? That might be better:

  1)  |41|67|   |34|00|69|   |24|78|   |58|62|64|
  2)  |24|67|   |34|00|69|   |41|78|   |58|62|64|
  3)  |24|00|   |34|62|69|   |41|67|   |58|78|64|
  4)  |24|00|   |34|62|64|   |41|67|   |58|78|69|
  5)  |00|24|34|62|64|41|67|58|78|69|
  6)  |00|24|34|41|62|64|67|58|78|69|
  7)  |00|24|34|41|58|62|64|67|78|69|
  8)  |00|24|34|41|58|62|64|67|69|78|

Sorting interleaved groups is the idea behind the diminishing increment sort, better known by the popular name Shell sort. Donald Shell capitalized on the fact that sorting by insertion is very fast for small arrays that are almost sorted. He then introduced the concept of breaking the array into increasing groups of smaller numbers (usually called the h-increment) of items. As long as the groups eventually shrink down to N groups of 1, the final step is a straight insertion and the algorithm terminates successfully:

void jsw_shellsort ( int a[], int n )
{
  int i, h = 1;

  while ( h <= n  9 )
    h = 3 * h + 1;

  while ( h > 0 ) {
    for ( i = h; i < n; i++ ) {
      int j, save = a[i];

      for ( j = i; j >= h && a[j - h] > save; j -= h )
        a[j] = a[j - h];

      a[j] = save;
    }

    h = 3;
  }
}

The only difference between this code and the insertion sort is that we've added an extra loop around the insertion sort that handles the step increments and replaced references to 1 with h. By moving items that are separated by a large number of items, they get closer to their final resting place faster. The examples above don't do the algorithm justice, but until quicksort was developed, Shell sort was the fastest sorting algorithm available.

A careless choice of values for the h-increments, such as powers of two, could result in strikingly bad performance, while a seemingly arbitrary sequence can result in very good performance. To date, nobody has determined what the very best sequence is. Two sequences known to be good are the square of the Fibonacci sequence (1,4,9,25,64,169,441,...), and a sequence recommended by Donald Knuth that's fast and easy to calculate (1,4,13,40,121,364,1093,3280,9841...). While there are better sequences, these two are not substantially worse, and they have the benefit of being easy to create with minimal cost. The function above uses Knuth's sequence.

The Shell sort is simple to understand, easy to implement, and has good performance for small to medium arrays, but its time complexity is difficult to analyze and depends heavily on the sequence of h-increments chosen. In general, Shell sort should be the first sort used because it's easier to implement than the higher order sorting algorithms (with the possible exception of heap sort) and has good performance. If Shell sort turns out to be too slow, then some of the faster algorithms can be considered.

Bubble Sort
Sorting by exchanging is just that. Pairs of items that are out of order are exchanged repeatedly until no more pairs exist. When no more pairs exist that are out of order, the array must be completely sorted. Sorting by exchanging is particularly dangerous because the efficient solutions aren't nearly as obvious as the hideously inefficient ones. This is true for all sorting categories, but sorting by exchanging has the great honor of boasting the worst sorting algorithm that you might see in the real world (if you're unlucky). Here is a look at the most obvious algorithm:

  1)  |41|67|34|00|69|24|78|58|62|64|
  2)  |41>34|67|00|69|24|78|58|62|64|
  3)  |41|34>00|67|69|24|78|58|62|64|
  4)  |41|34|00|67>24|69|78|58|62|64|
  5)  |41|34|00|67|24|69>58|78|62|64|
  6)  |41|34|00|67|24|69|58>62|78|64|
  7)  |41|34|00|67|24|69|58|62>64|78|
  8)  >34|41|00|67|24|69|58|62|64|78|
  9)  |34>00|41|67|24|69|58|62|64|78|
 10)  |34|00|41>24|67|69|58|62|64|78|
 11)  |34|00|41|24|67>58|69|62|64|78|
 12)  |34|00|41|24|67|58>62|69|64|78|
 13)  |34|00|41|24|67|58|62>64|69|78|
 14)  >00|34|41|24|67|58|62|64|69|78|
 15)  |00|34>24|41|67|58|62|64|69|78|
 16)  |00|34|24|41>58|67|62|64|69|78|
 17)  |00|34|24|41|58>62|67|64|69|78|
 18)  |00|34|24|41|58|62>64|67|69|78|
 19)  |00>24|34|41|58|62|64|67|69|78|

As you can clearly see, this particular exchange sort is exceptionally inefficient, even when compared to straight selection and insertion, which have similar time complexity properties, even when the execution left out any of the steps that didn't result in a swap. Hey, I don't want to spend half my life typing out those executions, so I made it shorter. In the process I made the algorithm look better than it is, and it STILL looks bad. ;-)

Unfortunately, because the algorithm is simple and easy to understand this so-called �bubble sort� is commonly taught to beginning programmers as the first sorting algorithm, and often as a first algorithm entirely. I think that's a shame, because bubble sort only has practical use in very specific and unlikely circumstances, and for everything else it just sucks too much. For comparison and completeness, I'll provide an implementation of the bubble sort as it's usually taught:

void jsw_bubblesort ( int a[], int n )
{
  int i;

  for ( i = 0; i < n; i++ ) {
    int j;

    for ( j = n - 1; j > 0; j-- ) {
      if ( a[j] < a[j - 1] )
        jsw_swap ( &a[j], &a[j - 1] );
    }
  }
}

Well, you have to admit that it's simple. Of course, once you optimize it a bit, that simplicity starts to go away. A flag for testing whether a swap has been made is critical for bubble sort, because otherwise it would make several unnecessary passes over the collection before terminating. While strictly optional, a test for early completion is considered a mandatory optimization to the bubble sort algorithm. No further optimizations are necessary as they won't improve the performance significantly, and simpler algorithms, such as insertion sort, will almost always outperform it. Here's the �optimized� bubble sort:

void jsw_bubblesort ( int a[], int n )
{
  int i;

  for ( i = 0; i < n; i++ ) {
    int j, done = 1;

    for ( j = n - 1; j > 0; j-- ) {
      if ( a[j] < a[j - 1] ) {
        jsw_swap ( &a[j], &a[j - 1] );
        done = 0;
      }
    }

    if ( done )
      break;
  }
}

Bubble sort is a quadratic algorithm, but it's frighteningly inefficient even if you only compare it with other quadratic algorithms. Words can't describe my loathing for this algorithm, and I've gotten into very heated debates about whether it should ever be used or not, even as an introductory algorithm. My recommendation: forget bubble sort exists. You'll be better off for it. :-)

Quicksort
Bubble sort is unmercifully slow. It's the worst possible sorting algorithm that you'll see in the real world, and even then only because the author of the code probably doesn't know any better. Fortunately, we can improve bubble sort in much the same way that we improved the straight selection sort. But since we don't have a neat and tidy concept to improve, along with a way to improve it (ie. the selection problem), we need another way to improve the performance of exchanging. 

The good news is that we can use recursion to split the array at a median value at each step by moving the median value to its sorted position, then recursively sort each subarray the same way in a very good algorithm called quicksort. By dividing the problem at the median each time, we can guarantee that this part of the algorithm is O(log N). Now it's just a simple matter of figuring out a good way to sort the subarrays that doesn't take longer than O(N) and we'll have an optimal comparison sort.

Okay, maybe it's not that simple. :-) We have two immediate problems. First we need a way to partition the array. Partitioning is forcing a median value to its sorted position while making sure that all items less than the median come before it and all items greater than or equal to the median come after it. Then we need a way to find the median value without taking too much time. To really find the median requires at least an O(N) algorithm on top of the partitioning which will at best be O(N). Now, O(N) + O(N) is still O(N), but the algorithm will run more slowly than if we only had one O(N) part, and we want this to be as fast as possible.

Rather than waste cycles trying to find the true median, we'll just guess. Our first attempt at guessing is the simplest. We just take the first item in the subarray and pretend that it's the median value. :-) This could be a serious problem if the first item is the smallest item in the array, but we'll look at that a bit later. One problem at a time. Assuming a partition function, we can easily write a recursive function to partition, then recursively do the same thing on each subarray as long as the subarray has more than one item:

void jsw_quicksort_r ( int a[], int first, int last )
{
  if ( first < last ) {
    int pivot = jsw_partition ( a, first, last );
    jsw_quicksort_r ( a, first, pivot - 1 );
    jsw_quicksort_r ( a, pivot + 1, last );
  }
}

void jsw_quicksort ( int a[], int n )
{
  jsw_quicksort_r ( a, 0, n - 1 );
}

Let's look at a sample execution to see how this function could possibly work. It's not obvious at first unless you're familiar with recursion and can see how partitioning forces an item to its sorted position recursively results in a sorted file. In this example, we take the first item in each subarray and use it as the median and ignore cases where the subarray is too small to partition:

 |41|67|34|00|69|24|78|58|62|64|
 |41|34|00|24|58|62|64|69|67|78|
 |41|34|00|24|58|62|
 |41|34|00|24|58|
 |00|24|41|34|
 |00|24|34|41|58|62|64|
                      |69|67|78|
 |00|24|34|41|58|62|64|67|69|78|

The base case for recursion is when the indices first and last cross. So we stop the recursion if we get to a subarray with only a single item. jsw_quicksort passes an inclusive array to jsw_quicksort_r, which basically means that both a[first] and a[last] are valid items. This is different from most of our other algorithms (such as heap sort) where last is the first index after the last element of the array. This is for the benefit of jsw_partition, which is more easily written if both first and last refer to valid indices. The pivot variable refers to the index of the median value so there's no need to include it in the recursive calls as it's already sorted after partitioning. Here's the code that performs the partition magic:

int jsw_partition ( int a[], int first, int last )
{
  int pivot = first;

  while ( first < last ) {
    if ( a[first] <= a[last] )
      jsw_swap ( &a[pivot++], &a[first] );

    ++first;
  }

  jsw_swap ( &a[pivot], &a[last] );

  return pivot;
}

Partitioning an array is surprisingly difficult to get right. The algorithm above is a relatively safe, simple, and efficient one that gets the job done in O(N) time. The idea is to walk across the array, swapping the pivot with items that are less than the pivot as we go, and resetting the pivot to the next item when we swap. When we get to the end of the array, the current pivot is the median value that's in its sorted position. Note that the median isn't necessarily the pivot that we chose at the beginning of the partition.

That's all there is to quicksort! Once you have a partition algorithm that works, writing the code to do a quicksort is trivial, and then you have the fastest non-hybrid sorting algorithm at your disposal. But we're not done yet because we can improve the algorithm. There are a few problems that need to be fixed and optimizations that can make quicksort even faster.

The first problem is the biggest. If the pivot value chosen in jsw_partition is always the smallest item in the array, such as when the array is already sorted, no swaps will be made and the median will be the first item in the array. This results in a vastly unbalanced split where the left half has one item and the right half has the rest of the array. This is a degenerate case where quicksort really isn't that quick, with a quadratic time complexity.

There are two widely accepted ways to minimize the chances of hitting a degenerate case. First, we can use a random number generator to pick which value in the array to use as a pivot. Then we guarantee that nothing untoward can happen by swapping that value with the first item in the array because the partition algorithm assumes that pivot starts at first. Otherwise we would end up walking off the end of the array, and that's never a good thing. ;-) The changes are minimal:

int jsw_partition ( int a[], int first, int last )
{
  int pivot = first + rand() % ( last - first + 1 );

  jsw_swap ( &a[pivot], &a[first] );
  pivot = first;

  while ( first < last ) {
    if ( a[first] <= a[last] )
      jsw_swap ( &a[pivot++], &a[first] );

    ++first;
  }

  jsw_swap ( &a[pivot], &a[last] );

  return pivot;
}

Notice that the code to find a random index within the range is somewhat complicated. We need to take into account that first is not always zero, so we use last - first + 1 to find the number of items in the subarray (we add 1 because last is the last valid item, not one beyond the last valid item), then use that as the modulus for rand (ignoring the issues with rand). Finally, because the resulting number is ranged from zero to the number of elements, we add first to fit it within the range of [first,last] as a valid index.

The second, and preferred, option is to take the median of three items picked at random from the array (though the first, last, and middle are most common), and use that as the pivot. The process is the same, except instead of picking a random index and swapping its item with a[first], we pick the median of a[first], a[mid], and a[last], then swap that median with a[first]:

int jsw_partition ( int a[], int first, int last )
{
  int pivot, mid = ( first + last ) / 2;

  /* Largest of two */
  pivot = a[first] > a[mid] ? first : mid;

  /* Smallest of remaining */
  if ( a[pivot] > a[last] )
    pivot = last;

  jsw_swap ( &a[pivot], &a[first] );
  pivot = first;

  while ( first < last ) {
    if ( a[first] <= a[last] )
      jsw_swap ( &a[pivot++], &a[first] );

    ++first;
  }

  jsw_swap ( &a[pivot], &a[last] );

  return pivot;
}

The next improvement is an optimization that doesn't touch jsw_partition (yay!). Since it's really a waste to recurse on small subarrays, we can set a threshold for when to stop calling jsw_quicksort_r recursively. As it is, we're recursing until first and last cross, which is equivalent to a threshold of 0. But if we set a cutoff of, say, 15 or 20, we can mostly sort a large array, then hand it off to insertion sort, which is much faster for small or nearly sorted arrays. This suggests two possible variations. First, we could call insertion sort inside jsw_quicksort_r, if we get to the cutoff. Robert Sedgewick studied this thoroughly and discovered that it's slightly more efficient to call insertion sort after quicksort finishes, which brings us to this (where THRESHOLD is a macro with whatever cutoff value you choose):

void jsw_quicksort_r ( int a[], int first, int last )
{
  if ( last - first > THRESHOLD ) {
    int pivot = jsw_partition ( a, first, last );
    jsw_quicksort_r ( a, first, pivot - 1 );
    jsw_quicksort_r ( a, pivot + 1, last );
  }
}

void jsw_quicksort ( int a[], int n )
{
  jsw_quicksort_r ( a, 0, n - 1 );
  jsw_insertion ( a, n );
}

The next optimization that we'll look at handles the problem of already sorted subarrays. If the subarrays are already sorted or have a large number of duplicates, quicksort will take its sweet time going through them all. There's no point in using a sophisticated sort on an already sorted subarray, and we can make quicksort consistently fast by testing if the subarray is already sorted and doing nothing if it is. The change is made to jsw_quicksort_r, and we can use the is_sorted function given earlier:

void jsw_quicksort_r ( int a[], int first, int last )
{
  if ( last - first > THRESHOLD ) {
    int pivot;

    if ( is_sorted ( a, first, last ) )
      return;
    
    pivot = jsw_partition ( a, first, last );
    jsw_quicksort_r ( a, first, pivot - 1 );
    jsw_quicksort_r ( a, pivot + 1, last );
  }
}

You might be thinking that calling a linear function might have performance issues, but in practice it actually makes quicksort faster. But that's still not the best implementation! It's fast, yes. It's definitely a very good quicksort, and a good compiler will give you efficient machine code for it. But a not so good compiler probably won't take care of the tail recursion in jsw_quicksort_r. Removing recursion is the last optimization for quicksort, and I'll leave it to you because I'm evil. >:)

As an aside, the worst case of quicksort is still O(N2) even though we've shrunk the possibility of encountering it to virtually nothing. However, by putting together several sorting algorithms into a hybrid �super-algorithm�, we can have our cake and eat it too. Here are the common players:

Heap sort: O(Nlog N) in the average and worst cases, but still slower than quicksort due to more comparisons.

Quicksort: O(Nlog N) in the average case, but O(N2) in the worst case. Fast as greased lightning if the worst case isn't encountered though.

Insertion sort: O(N2) in the average case, but O(N) if the array is already sorted or almost sorted.

Here's what we're going to do. We'll use quicksort until it's obvious that we're nearing a degenerate case. We can test for that by figuring out the depth of recursion that qualifies as O(log N). When we get to that depth, we're starting to leave the boundaries of quicksort's average case. Once we hit that cutoff, we then switch to heap sort because it's guaranteed to be O(Nlog N). By doing this, we never leave a complexity of O(Nlog N). We can also implement all of the optimizations for quicksort such as the threshold and insertion sort at the end, as well as already sorted subarrays. The resulting algorithm is called introsort, short for introspective sort because it's smart enough to change how it works when things start to get hairy:

void jsw_introsort_r ( int a[], int first, int last, int depth )
{
  if ( last - first > THRESHOLD ) {
    if ( depth == 0 )
      jsw_heapsort ( &a[first], last - first + 1 );
    else {
      int pivot;

      if ( is_sorted ( a, first, last ) )
        return;
    
      pivot = jsw_partition ( a, first, last );
      jsw_introsort_r ( a, first, pivot - 1, depth - 1 );
      jsw_introsort_r ( a, pivot + 1, last, depth - 1 );
    }
  }
}

void jsw_introsort ( int a[], int n )
{
  jsw_introsort_r ( a, 0, n - 1, (int)( 2 * log ( n ) ) );
  jsw_insertion ( a, n );
}

Heap sort and quicksort remain unchanged, as does insertion sort, but we need to be careful to only call heapsort on the correct subarray, which means passing an array slice. Introsort only puts them together into an algorithm that guarantees good performance in all cases. But we can improve even this beautiful algorithm by paring it down to trim the fat. Since there's a logarithmic cutoff on the depth of the recursion, we can remove the left side recursion in favor of a loop. This change helps to negate any overhead that introsort might have so that it's that much closer to a plain quicksort in the average case:

void jsw_introsort_r ( int a[], int first, int last, int depth )
{
  while ( last - first > THRESHOLD ) {
    if ( depth == 0 )
      jsw_heapsort ( &a[first], last - first + 1 );
    else {
      int pivot;

      if ( is_sorted ( a, first, last ) )
        return;
    
      pivot = jsw_partition ( a, first, last );
      jsw_introsort_r ( a, pivot + 1, last, depth - 1 );
      last = pivot - 1;
    }
  }
}

Note that heap sort isn't a requirement. You can use any sorting algorithm that guarantees at least O(Nlog N) performance, such as merge sort or radix sort. However, heap sort has an added benefit that it sorts in-place while merge sort and radix sort require extra memory to temporarily store subarrays. The same goes for insertion sort. Any sort that's most efficient with almost sorted arrays will work just as well.

Merge Sort
One of the first sorting methods suggested was by John Von Neumann. The concept is simple: split an array into two parts, sort those two parts, then merge them together. This is generally done recursively, where each subarray is then separated into two smaller subarrays, those subarrays are separated into four smaller subarrays, and so on until you have N subarrays of 1 item. At that point, you merge all of the subarrays together and the array is sorted. The basic code for this process is similar to quicksort:

void jsw_mergesort_r ( int a[], int first, int last )
{
  if ( first < last - 1 ) {
    int mid = ( first + last ) / 2;
    jsw_mergesort_r ( a, first, mid );
    jsw_mergesort_r ( a, mid, last );
    jsw_merge ( a, first, mid, last );
  }
}

void jsw_mergesort ( int a[], int n )
{
  jsw_mergesort_r ( a, 0, n );
}

It seems as if merge sort is the inverse of quicksort. Where quicksort first partitions and then recurses, merge sort recurses and then merges, which is a reasonable observation. As with quicksort, if the merge operation is assumed to work properly, the algorithm is easy to visualize, even if it's difficult to describe. Also, while the recursive scheme works for arrays in fast memory, merge sort's claim to fame is that it can easily be modified to handle sequential data such as from a stream or a generator. As such, merge sort is excellent for sorting large linked lists, and it's often the algorithm of choice for external sorting of files that are too large to fit in fast memory all at one time.

It's a good idea, as with quicksort's partition, to choose the simplest merge algorithm available. The process of merging is one of the deceptively simple algorithms in computer science. Given two arrays, compare each item with the other as they come and assign the smallest to the final array. When one of the sequences is exhausted, copy the other in bulk to the final array. Here is one algorithm, called straight merging, that's easy to understand and works well in many cases:

void jsw_merge ( int a[], int first, int mid, int last )
{
  int i = first, j = mid, k = 0;
  int *save = malloc ( ( last - first ) * sizeof *save );

  while ( i < mid && j < last ) {
    if ( a[i] <= a[j] )
      save[k++] = a[i++];
    else
      save[k++] = a[j++];
  }

  while ( i < mid )
    save[k++] = a[i++];

  while ( j < last )
    save[k++] = a[j++];

  for ( i = 0; i < ( last - first ); i++ )
    a[first + i] = save[i];

  free ( save );
}

The merge simply works with two subarrays: a left subarray from first to mid, and a right subarray from mid to last. As long as there are items in both subarrays, we copy the smallest of them to the temporary buffer and move only the index for the buffer and the subarray forward. After one of the subarrays is exhausted, we copy the remaining subarray to the buffer, then copy the buffer to the original array and terminate (but not before freeing the memory we allocated). Here's an execution trace of the entire sorting algorithm (leaving out the base cases because they do nothing):

 |41|67|34|00|69|24|78|58|62|64|
 |41|67|34|00|69|
 |41|67|
       |34|00|69|
          |00|69|
       |00|34|69|
 |00|34|41|67|69|
                |24|78|58|62|64|
                |24|78|
                      |58|62|64|
                         |62|64|
                      |58|62|64|
                |24|58|62|64|78|
 |00|24|34|41|58|62|64|67|79|78|

It should be immediately obvious that for the merge algorithm to work, extra space equal to the size of the array is required. If we didn't use a temporary buffer, we might copy over the current item in one of the subarrays and lose it forever. That's not conducive to a correct sorting algorithm, so we live with the extra memory for a buffer.

The extra space requirement can be removed so that the merge runs in-place, but the resulting algorithm is both complicated and slower, so extra space is a necessary evil for an efficient merge sort using arrays. This is why the merge sort is well suited to linked lists; an item can simply be spliced in and out of a list representing the merged halves without using any extra space, aside from a pointer or two.

The running time of a merge sort is largely insensitive to the order of the items, so it has guaranteed performance properties. This is in contrast to, for example, quicksort, where certain degenerate orders can cause the running time of the algorithm to drop from O(Nlog N) to O(N2). On the other hand, because guaranteed performance is a double edged sword, a straight merge sort can't take advantage of any inherent order already in the array to improve its running time. Insertion sort is very fast, approaching and sometimes reaching O(N), if the array is almost sorted, and other algorithms can take advantage of the distribution of items to run very quickly.

Of course, like quicksort we can add a test to see if the subarray is already sorted and avoid recursing on it. This counts as an introspective algorithm that takes advantage of existing order in the subarray. It also could be educational to try the threshold trick we got from quicksort on merge sort, where we stop at a certain cutoff to make the array almost sorted and finish the algorithm with an insertion sort. Remember that tricks from one sorting algorithm can sometimes be reused in other algorithms.

You might notice that while I said that merge sort is ideal for data that can only be accessed sequentially, the merge sort algorithm above actually relies heavily on random access for its speed and requires that all of the items be present before the algorithm can be run so that it can find the middle item. The same algorithm with a linked list would be much slower because finding the middle of a list if you are only given the head is somewhat expensive. The best solution is to walk two links down the list, one moving twice as fast. When the faster link reaches the end of the list, the slower link is at the middle. The code to split a list in this way and then sort it by merging is relatively simple. The split is easy to write, the merge is far easier to write and far shorter, and the sort really doesn't change that much:

struct jsw_node *jsw_split ( struct jsw_node *a )
{
  struct jsw_node *b = a->next;

  while ( b != NULL && b->next != NULL ) {
    a = a->next;
    b = b->next->next;
  }

  b = a->next;
  a->next = NULL;

  return b;
}

struct jsw_node *jsw_merge (
  struct jsw_node *a, struct jsw_node *b )
{
  struct jsw_node result, *it = &result;
  struct jsw_node **half;

  while ( a != NULL && b != NULL ) {
    half = ( a->data < b->data ) ? &a : &b;
    it->next = *half;
    it = *half;
    *half = (*half)->next;
  }

  it->next = ( a == NULL ) ? b : a;

  return result.next;
}

struct jsw_node *jsw_mergesort_r ( struct jsw_node *a )
{
  if ( a != NULL && a->next != NULL ) {
    struct jsw_node *b = jsw_split ( a );

    a = jsw_mergesort_r ( a );
    b = jsw_mergesort_r ( b );

    return jsw_merge ( a, b );
  }

  return a;
}

void jsw_mergesort ( struct jsw_list *list )
{
  list->head = jsw_mergesort_r ( list->head );
}

However, as I've already said several times, jsw_split slows down the algorithm by a substantial amount, so this algorithm isn't very practical. A much better option is to take items sequentially from the beginning, do some magic, and then merge the magical result into a sorted array or list. This is much better suited to a sequential delivery method such as a stream or generator, and it improves the performance of the sort on linked lists considerably.

Because we are accepting items as they exist in the collection, we can guarantee that the algorithm is stable. We can also take advantage of the current order of the collection, unlike with straight merge sorting. Such an algorithm is called a �natural� merge, because it uses the natural order of the collection to improve its performance. The worst case of a natural merge sort is O(Nlog N), but the best case is O(N). This is an improvement over guaranteed O(Nlog N) performance in all cases because if the array is already sorted or almost sorted, the performance is as good as running insertion sort from the beginning.

The algorithms for a natural merge sort can vary wildly, but a simple algorithm that performs well uses two queues to act as each half of the merge. The first item goes into queue A, and for each new item, if the item is smaller than the top of the current queue, the algorithm switches queues. Because we switch queues only when the order of the sequence changes, the number of items in each queue won't be balanced. In fact, all of the items in the array could be in one queue, in which case the array is completely sorted. Here's the code to do a natural merge sort with arrays and queues:

void jsw_merge ( int a[], int *q[2], int top[2] )
{
  int i[2] = {0}, k = 0;
  int dir = q[1][0] < q[0][0];

  a[k++] = q[dir][i[dir]++];

  while ( i[dir] < top[dir] ) {
    dir = q[1][i[1]] < q[0][i[0]];

    /* Special case: Use larger item */
    if ( q[dir][i[dir]] < a[k - 1]
      && a[k - 1] < q[!dir][i[!dir]] )
    {
      dir = !dir;
    }

    a[k++] = q[dir][i[dir]++];
  }

  while ( i[0] < top[0] )
    a[k++] = q[0][i[0]++];
  while ( i[1] < top[1] )
    a[k++] = q[1][i[1]++];
}

void jsw_mergesort ( int a[], int n )
{
  int *q[2], top[2];
  int half, i;

  if ( n < 2 )
    return;

  q[0] = malloc ( n * sizeof *q[0] );
  q[1] = malloc ( n * sizeof *q[1] );

  for ( ; ; ) {
    top[0] = top[1] = 0;
    q[0][top[0]++] = a[0];
    half = 0;

    for ( i = 1; i < n; i++ ) {
      if ( a[i] < q[half][top[half] - 1] )
        half = !half;

      q[half][top[half]++] = a[i];
    }

    if ( top[0] == 0 || top[1] == 0 )
      break;

    jsw_merge ( a, q, top );
  }

  half = top[0] == 0;

  for ( i = 0; i < n; i++ )
    a[i] = q[half][i];

  free ( q[0] );
  free ( q[1] );
}

Notice that jsw_merge no longer needs to allocate memory because that memory is allocated in jsw_mergesort to the queues, and then the queues are passed to jsw_merge. This makes the merge simpler and faster because we're not constantly calling an expensive memory manager. A simple boolean flag is used to switch between queues. This works because we only have two queues, so the only valid indices are 0 and 1. That coincides perfectly with the result of a boolean test. However, we need to be careful to reset the queues on each iteration of the outer loop (by setting the tops to 0 and giving the first queue the first item in the array).

Let's look at an example, because this algorithm could easily be confusing. :-) The following execution depicts the worst case for a natural merge sort (where the algorithm has O(Nlog N) performance). The worst case is an already sorted array in descending order, which is basically the opposite of what we want (in this tutorial we're sorting in ascending order). Pay careful attention to how the two queues work together to sort the array:

          Result              Queue A             Queue B
 1)  |8|7|6|5|4|3|2|1|   | | | | | | | | |   | | | | | | | | |
 2)  |7|5|3|1|8|6|4|2|   |8|6|4|2| | | | |   |7|5|3|1| | | | |
 3)  |5|1|7|3|6|2|8|4|   |7|3|6|2| | | | |   |5|1|8|4| | | | |
 4)  |1|5|3|6|4|7|2|8|   |5|3|6|4| | | | |   |1|7|2|8| | | | |
 5)  |1|3|5|4|6|2|7|8|   |1|5|4|7| | | | |   |3|6|2|8| | | | |
 6)  |1|3|4|5|2|6|7|8|   |1|3|5|2|7|8| | |   |4|6| | | | | | |
 7)  |1|2|3|4|5|6|7|8|   |1|3|4|5| | | | |   |2|6|7|8| | | | |
 8)  |1|2|3|4|5|6|7|8|   |1|2|3|4|5|6|7|8|   | | | | | | | | |

It's possible to modify the algorithm to eliminate the need for two queues, but the result is dreadfully complicated and only serves to confuse most of the people that look at it. :-) The only problem with using two queues implemented as arrays is that both have to be at least as big as the array itself, so you are looking at an extra space cost of 2N instead of N. However, using a dynamic queue can decrease that cost while causing the algorithm to potentially run slower.

The extra extra space for a natural merge sort on arrays isn't such a bad thing because you shouldn't use a natural merge sort on arrays in the first place. Even though a natural merge sort on an array is theoretically better than a straight merge sort, in practice it's much slower due to excessive copying of data in and out of the queues. However, the natural merge sort is ideal for linked lists because by splicing nodes, you avoid the problem of copying data all over the place. Here's a tuned natural merge sort for linked lists:

/* 
  Remove a node from a list and
  push it onto a tail pointer
*/
#define split_push(head,tail,item) do { \
  struct jsw_node *save = item->next; \
  item->next = NULL; \
  if ( tail == NULL ) \
    head = tail = item; \
  else { \
    tail->next = item; \
    tail = tail->next; \
  } \
  item = save; \
}while ( 0 );

struct jsw_node *jsw_merge ( struct jsw_node *a, 
  struct jsw_node *q[2] )
{
  int dir = q[0]->data > q[1]->data;
  struct jsw_node *save = a = q[dir];

  /* Intended assignment */
  while ( q[dir] = q[dir]->next ) {
    dir = q[0]->data > q[1]->data;

    if ( q[dir]->data < a->data 
      && a->data < q[!dir]->data )
    {
      dir = !dir;
    }

    a->next = q[dir];
    a = a->next;
  }

  dir = q[0] == NULL;

  while ( q[dir] != NULL ) {
    a->next = q[dir];
    q[dir] = q[dir]->next;
    a = a->next;
  }

  return save;
}

void jsw_mergesort ( struct jsw_list *list )
{
  struct jsw_node *q[2] = {0};
  struct jsw_node *a = list->head;

  for ( ; ; ) {
    struct jsw_node *end[2] = {0};
    int half = 0;

    split_push ( q[0], end[0], a );

    while ( a != NULL ) {
      if ( a->data < end[half]->data )
        half = !half;
      split_push ( q[half], end[half], a );
    }

    if ( q[0] == NULL || q[1] == NULL )
      break;

    a = jsw_merge ( a, q );
  }

  list->head = q[q[0] == NULL];
}

Not only is the code simpler (assuming you're familiar with linked lists), it's also much faster than the array version. The extra space cost has virtually been eliminated because the queues are nothing more than pointers to nodes that already exist, so no extra memory needs to be allocated. jsw_merge is just a translation of the natural merge algorithm used for arrays to linked lists, and split_push is nothing more than a specialized way to extract a node from the list and push it onto a queue.

The performance properties of merge sort are very good. It has guaranteed O(Nlog N) performance, like heap sort, and when a natural merge sort is used it can reach O(N) performance, but the performance of merge sort comes at the price of extra space equivalent to the number of items being sorted. This cost is eliminated when sorting linked lists, which is why merge sort is a common list sorting algorithm. When the merge algorithm is chosen carefully, mergesort is one of the few stable sorting algorithms. Most other high speed sorting algorithms that can handle large arrays or lists require extra work and extra space to make them stable, so in light of the stability question, mergesort fares very well. Another huge benefit is that when written carefully, merge sort does not require that all items be present. It can sort an unknown number of items coming in from a stream or generator, which is a very useful property.

Radix Sort
Up to this point, we've looked mostly at algorithms that sort by comparison. That is, we figure out the relative order of two items by testing which is less than the other and place them accordingly. This section will cover a different method, where we use the distribution of items and place them in buckets, then put the buckets together to form a final sorted array. The first algorithm that uses distribution is called counting sort. The concept is to map each item to an array, where the item's value is the array index. Then you count how many items are smaller than that item, each time incrementing the index. Then you use the count as a location index to move the item to its final location.

Here's the process on an array of 10 items ranged from [0,10) using a 1-based index algorithm described in Donald Knuth's �The Art of Computer Programming�, volume 3:

 |1|7|4|0|9|4|8|8|2|4|

 Get counts:

 |0|1|1|1|0|3|0|0|1|2|1|

 Count smaller items:

 |0|1|2|3|3|6|6|6|7|9|1|

 Use counts as indices:

 |0|1|2|4|4|4|7|8|8|9|

It's a nifty algorithm, but when I first read about it, I wasn't able to completely understand what was going on until I walked through it on paper, so I won't try to explain in detail. I'll leave you with the basic concept, the code, and let you do the same thing (probably because I'm evil). There's a lot to be said for working out algorithms on paper though. :-) Here's the code that does a counting sort. Be sure to figure it out before moving on, because this will be a fundamental part of the coming radix sorts. Be happy that it's in C, I had to translate it from MIX...

void jsw_countsort ( int a[], int m, int n )
{
  int *aux = malloc ( n * sizeof *aux );
  int *count = calloc ( m + 1, sizeof *count );
  int i;

  for ( i = 0; i < n; i++ )
    ++count[a[i] + 1];

  for ( i = 1; i < m; i++ )
    count[i] += count[i - 1];

  for ( i = 0; i < n; i++ )
    aux[count[a[i]]++] = a[i];

  for ( i = 0; i < n; i++ )
    a[i] = aux[i];

  free ( count );
  free ( aux );
}

As we discovered previously in the tutorial, the lower bound for sorting algorithms that use comparisons to find the relative order of items is O(Nlog N). However, it's possible to improve that to O(N) by eschewing comparisons and using distribution as the counting sort did. Counting sort is a linear algorithm because it makes a set number of linear passes through the array, regardless of pre-existing order.

However, the biggest problem with counting sort is that it requires extra memory equivalent to the range of items being sorted. So if you have 10 items in the range of [0,1,000,000), you need to allocate an extra array to hold the counts for one million items. That's a ridiculous requirement, and it makes counting sort far less practical than other sorting algorithms. If only we could figure out a way to use counting sort but minimize the extra space we need to allocate for the counts.

This idea is exactly what a class of algorithms called radix sort do. Instead of using the full range of each item, they use the range of a single digit, for some definition of �digit�, and then use a distribution sort on each digit either from the most significant digit to the least significant digit or vice versa. The two algorithms called radix sort are LSD (for �least significant digit�, you druggies!), and MSD (for most significant digit). The LSD algorithm is what was used to sort punch cards back in the early days of computing.

Before we get into the code, let's look at an example execution where we start at the least significant digit of several 3 digit numbers and use counting sort until we get to the most significant digit:

   1     2     3     4
 -----------------------
 |341| |100| |100| |100|
 |267| |341| |224| |178|
 |534| |762| |534| |224|
 |100| |534| |341| |267|
 |369| |224| |958| |341|
 |224| |564| |762| |369|
 |178| |267| |564| |534|
 |958| |178| |267| |567|
 |762| |958| |369| |762|
 |564| |369| |178| |958|

There are several things to remember about LSD radix sort. Each digit needs to be sorted with a stable algorithm. The most common choice is a counting sort because counting sort is an algorithm that can reach O(N) performance. If you have short keys then LSD radix sort can also be O(N), whereas if we used another stable sort like a straight shift select, each digit would be sorted with an O(N2) sort, and the entire algorithm would become quadratic. Next, each key has to be the same length. That's why most radix sorts will use the number of bytes as the radix, so 4 byte integers would be sorted from the least significant byte to the most significant byte, where each byte is a digit. The performance of any radix sort is dependent on the length of the items.

With this in mind, LSD radix sort is relatively easy to implement. You simply modify a counting sort to use digits, then call the counting sort on each digit of the array. The auxiliary array that counting sort uses can be allocated in the function that calls the counting sort, so we avoid multiple calls to the memory manager. The nice thing about using counting sort for a radix sort is that the count array can be small. In our case, we only need to count all of the possible bytes, so the count array can be as small as ( 1U << CHAR_BIT ) + 1, which is exactly what we do. :-)

#define RANGE ( ( 1U << CHAR_BIT ) + 1 )
#define digit(x,i) ( (x) >> ( (i) * CHAR_BIT ) & UCHAR_MAX )

void jsw_radix_pass ( int a[], int aux[], int n, int radix )
{
  int i;
  int count[RANGE] = {0};

  for ( i = 0; i < n; i++ )
    ++count[digit ( a[i], radix ) + 1];

  for ( i = 1; i < RANGE; i++ )
    count[i] += count[i - 1];

  for ( i = 0; i < n; i++ )
    aux[count[digit ( a[i], radix )]++] = a[i];

  for ( i = 0; i < n; i++ )
    a[i] = aux[i];
}

void jsw_radixsort ( int a[], int n )
{
  int i;
  int *aux = malloc ( n * sizeof *aux );

  for ( i = 0; i < sizeof *a; i++ )
    jsw_radix_pass ( a, aux, n, i );

  free ( aux );
}

The biggest problem with LSD radix sort is that it starts at the digits that make the least difference. If we could start with the most significant digits, the first pass would go a long way toward sorting the entire range, and each pass after that would simply handle the details. The idea of MSD radix sorting is to divide all of the digits with an equal value into their own bucket, then do the same thing with all of the buckets until the array is sorted. Naturally, this suggests a recursive algorithm, but it also means that we can now sort variable length items and we don't have to touch all of the digits to get a sorted array. This makes MSD radix sort considerably faster and more useful.

 Original:

 |369|267|564|100|341|224|178|958|762|334|

 First Pass:

   1     2     3     4     5     6
 -----------------------------------
 |100| |267| |369| |564| |762| |958|
 |178| |224| |341|
             |334|

 Second Pass:

   1     2     3     4     5     6     7     8     9    10
 -----------------------------------------------------------
 |100| |178| |224| |267| |334| |341| |369| |564| |762| |958|

 Sorted:

 |100|178|224|267|334|341|369|564|762|958|

Notice that because all of the second digits are unique, no further sorting is needed beyond the second pass. Each of the buckets are separated into their own buckets containing items that have duplicate digits. So in the first pass, every item that started with 3 was put into a bucket, every item that started with 2 was put in a bucket, and so on. This is a good example of MSD radix sort being more efficient than LSD radix sort, which would have to sort all digits before the array would be sorted.

The bad news is that MSD radix sort is going to be recursive in this tutorial. It looks surprisingly similar to quicksort though, which is a good thing because we can use the threshold trick to stop before spending too much time on small buckets and finish the almost sorted array with insertion sort. jsw_radix_pass is pretty much the same thing, but for variety and to show the variable length item strength of MSD radix sort, we'll implement this one to sort strings instead of integers:

/* Extract ith MSD byte */
#define digit(x,i) ( (x)[i] )
#define bin(x) ( first + count[x] )

void jsw_radix_pass ( char *a[], char *aux[],
  int count[], int first, int last, int radix )
{
  int i;

  for ( i = first; i < last; i++ )
    ++count[digit ( a[i], radix ) + 1];

  for ( i = 1; i < UCHAR_MAX; i++ )
    count[i] += count[i - 1];

  for ( i = first; i < last; i++ )
    aux[count[digit ( a[i], radix )]++] = a[i];

  for ( i = first; i < last; i++ )
    a[i] = aux[i - first];
}

void jsw_radixsort_r ( char *a[], char *aux[],
  int first, int last, int radix )
{
  if ( radix <= UCHAR_MAX && last - first > THRESHOLD ) {
    int count[UCHAR_MAX + 1] = {0};
    int i;

    jsw_radix_pass ( a, aux, count, first, last, radix );

    for ( i = 0; i < UCHAR_MAX - 1; i++ ) {
      int left = bin ( i );
      int right = bin ( i + 1 ) - 1;
      jsw_radixsort_r ( a, aux, left, right, radix + 1 );
    }
  }
}

void jsw_radixsort ( char *a[], int n )
{
  char **aux = malloc ( ( n + 1 ) * sizeof *aux );

  jsw_radixsort_r ( a, aux, 0, n, 0 );
  jsw_insertion ( a, n );

  free ( aux );
}

MSD radix sort doesn't require a stable sort as the workhorse algorithm, even though we still used counting sort because it's fast. So MSD radix sort is considerably more flexible than LSD radix sort. One thing to be careful of is that in both the LSD and MSD algorithms, I've implemented 0 as �start here�, so LSD sees digits in 5,4,3,2,1,0 order while MSD sees digits in 0,1,2,3,4,5 order. In other words, be careful when mixing and matching because these algorithms can be very fragile.

Conclusion
The art of sorting is unbelievably diverse, and one single source can't possibly teach you everything there is to know about it. I regret that this tutorial can't be more comprehensive, but it was already too long when I felt that I included the bare minimum of information. I hope that this article was helpful, and I encourage you to read Donald Knuth's �The Art of Computer Programming� volume 3, which is considered the definitive text on sorting. However, keep in mind that it is somewhat out of date and that more recent discoveries on sorting will require more intensive searching to uncover...ironically enough. :-)


