I see at catch exception by pointer in C++ , it is said to throw an exception by value and catch it by reference.
Therefore, I write the following codes:
class CMyException : public CException
{
};
void CTestExceptionDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
throw CMyException();
}
However, this will cause compiler error:
1>TestExceptionDlg.cpp
1>d:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(763) : error C2248: 'CObject::CObject' : cannot access private member declared in class 'CObject'
1> d:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(561) : see declaration of 'CObject::CObject'
1> d:\program files (x86)\microsoft visual studio 9.0\vc\atlmfc\include\afx.h(532) : see declaration of 'CObject'
1> This diagnostic occurred in the compiler generated function 'CException::CException(const CException &)'
However, if I modify the codes to throw a newed exception, like this:
class CMyException : public CException
{
};
void CTestExceptionDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
throw new CMyException();
}
Then the error will disappear.
Why? This seems against the policy that one should throw exception by value and not allocate it from heap?
Update:
Below is the declaration of CException:
class AFX_NOVTABLE CException : public CObject
{
// abstract class for dynamic type checking
DECLARE_DYNAMIC(CException)
public:
// Constructors
CException(); // sets m_bAutoDelete = TRUE
explicit CException(BOOL bAutoDelete); // sets m_bAutoDelete = bAutoDelete
// Operations
void Delete(); // use to delete exception in 'catch' block
virtual BOOL GetErrorMessage(_Out_z_cap_(nMaxError) LPTSTR lpszError, _In_ UINT nMaxError,
_Out_opt_ PUINT pnHelpContext = NULL) const ;
virtual BOOL GetErrorMessage(_Out_z_cap_(nMaxError) LPTSTR lpszError, _In_ UINT nMaxError,
_Out_opt_ PUINT pnHelpContext = NULL);
virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);
// Implementation (setting m_bAutoDelete to FALSE is advanced)
public:
virtual ~CException() = 0;
BOOL m_bAutoDelete;
#ifdef _DEBUG
void PASCAL operator delete(void* pbData);
#if _MSC_VER >= 1200
void PASCAL operator delete(void* pbData, LPCSTR lpszFileName, int nLine);
#endif
protected:
BOOL m_bReadyForDelete;
#endif
};
Below is the declaration of CObject:
class AFX_NOVTABLE CObject
{
public:
// Object model (types, destruction, allocation)
virtual CRuntimeClass* GetRuntimeClass() const;
virtual ~CObject() = 0; // virtual destructors are necessary
// Diagnostic allocations
void* PASCAL operator new(size_t nSize);
void* PASCAL operator new(size_t, void* p);
void PASCAL operator delete(void* p);
#if _MSC_VER >= 1200
void PASCAL operator delete(void* p, void* pPlace);
#endif
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
// for file name/line number tracking using DEBUG_NEW
void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#if _MSC_VER >= 1200
void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine);
#endif
#endif
// Disable the copy constructor and assignment by default so you will get
// compiler errors instead of unexpected behaviour if you pass objects
// by value or assign objects.
protected:
CObject();
private:
CObject(const CObject& objectSrc); // no implementation
void operator=(const CObject& objectSrc); // no implementation
// Attributes
public:
BOOL IsSerializable() const;
BOOL IsKindOf(const CRuntimeClass* pClass) const;
// Overridables
virtual void Serialize(CArchive& ar);
#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
// Implementation
public:
static const CRuntimeClass classCObject;
#ifdef _AFXDLL
static CRuntimeClass* PASCAL _GetBaseClass();
static CRuntimeClass* PASCAL GetThisClass();
#endif
};