Cannot access private member declared in class 'CObject'... WTF?

If you're (still) using MFC, you will sometimes come across this error:

error C2248: 'CObject::CObject' : cannot access private member declared in class 'CObject'
    afx.h(535) : see declaration of 'CObject::CObject'
    afx.h(510) : see declaration of 'CObject'
    This diagnostic occurred in the compiler generated function 'CCmdTarget::CCmdTarget(const CCmdTarget &)'

The reason for this is quite obscure, but basically simple. It means you have invoked the copy constructor for the object that's throwing the error. Sadly Visual Studio will NOT point you at the offending object, it just barfs inside its own code, which is slightly less than no help at all. If you're dealing with a large codebase, this can be extremely annoying, and waste a large amount of time.

There are many possible generators, but only one underlying cause. One of the commonest coding mistakes that generates it in my experience is something like this. Imagine you've written a common function to do checkbox updating, like this:

void  CMyDlg::HandleDebugLevelClick (CButton btn, UINT level)
   if (btn.GetCheck () == 1)
      m_uDebugLevel |= level;
      m_uDebugLevel &= (~level);

void CMyDlg::OnBnClickedChkDbgLevelBasic()
   HandleDebugLevelClick (m_ctrl_chkDebugLevel_1, DEBUG_LEVEL_BASIC);

void CMyDlg::OnBnClickedChkDbgLevelDetail()
   HandleDebugLevelClick (m_ctrl_chkDebugLevel_2, DEBUG_LEVEL_DETAIL);

So you can see the click handlers call the common function and pass the button object, and some flag data. Boom, you just walked into this problem. The common function is taking a CButton, but it defaults to pass-by-value in C/C++, so you just invoked the copy constructor... which is private. For the purposes of demonstration I'm leaving aside the stupidity of passing a real-world entity like a button by value, but bear with me here. I've seen this three times in the real world, and two of those times I was the offender. It's easy to do when you're hacking code against a deadline.

In this case, the simple solution is to redefine the interface to the offending method like this:

void  CMyDlg::HandleDebugLevelClick (CButton& btn, UINT level)

So you're passing a reference, the copy constructor isn't invoked and the compiler will stop having a cow about it. But there are other routes to the same error. When you see it, don't panic, just bear in mind that you've invoked the copy constructor for something derived from CObject, and work your way up from there.