Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Compile errors trying to derive from CException

215 views
Skip to first unread message

bamfor...@googlemail.com

unread,
Apr 8, 2008, 9:54:40 AM4/8/08
to
Hello all, I'm having a problem creating a class derived from
CException in VS2005. Here's the class.:

class CIndexException : public CException
{
public:
CIndexException (const CIndexException & oSourceObject) :
m_pszMessage(oSourceObject.m_pszMessage) {};
CIndexException & operator = (const CIndexException & oSourceObject)
{
m_pszMessage = oSourceObject.m_pszMessage;
return *this;
};

CIndexException () : CException(), m_pszMessage(0) {};
CIndexException (char * pszError = 0, bool bAutoDelete = true) :
CException(bAutoDelete), m_pszMessage(pszError) {};
const char * GetMessage() { return m_pszMessage; }
protected:
char * m_pszMessage;
};


The build errors I'm getting are as follows:
Error 2 error C2248: 'CObject::CObject' : cannot access private member
declared in class 'CObject' c:\program files\microsoft visual studio
8\vc\atlmfc\include\afx.h 898
Error 4 error C2248: 'CObject::CObject' : cannot access private member
declared in class 'CObject' c:\program files\microsoft visual studio
8\vc\atlmfc\include\afx.h 898


I introduced the copy and assignment constructors thinking they would
remove the errors but they haven't. Would appreciate any help/
suggestions to get this working.

Many thanks in advance.

Joseph M. Newcomer

unread,
Apr 8, 2008, 10:58:12 AM4/8/08
to
Given you should never be using CIndexException at all, only CIndexException*, I don't
understand why you would need any kind of assignment operator. MFC will not work properly
with throwing a CIndexException; the correct code would be
throw new CIndexException;

Also, you should ABSOLUTELY get rid of 'char' as a data type! At the very least, you
should use
LPCTSTR GetMessage() { return m_pszMessage; }
and declare the variable as
LPTSTR m_pszMessage;
although it is seriuosly questionable why you would want a pointer to a string here at
all. And why are you initializing a pointer to 0 when you should initialize it to NULL?

The corrected code should read
CIndexException(LPCTSTR pszError = NULL, bool bAutoDelete = true) :
CException(bAutoDelete), m_pszMessage(pszError)) {}
and declare the string as
CString pszError;

otherwise, you have no idea if the pointer is valid at the point where the GetMessage is
called. CString forces a copy to be made (and don't even THINK of saying anything about
"efficiency"; you are throwing an exception, which is already an expensive operation, and
therefore the cost of constructing a CString is going to be irrelevant...besides, this
only happens when things go wrong!)

And I would actually write GetMessage as
CString GetMessage() { return pszError; }

There is very little justification for using raw character array pointers (and NEVER to
'char', always to TCHAR, that is, LPTSTR or LPCTSTR).
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Giovanni Dicanio

unread,
Apr 8, 2008, 12:17:53 PM4/8/08
to

<bamfor...@googlemail.com> ha scritto nel messaggio
news:ef7ed525-1ac4-49c0...@u10g2000prn.googlegroups.com...

> I introduced the copy and assignment constructors thinking they would
> remove the errors but they haven't. Would appreciate any help/
> suggestions to get this working.

As Joe wrote, MFC CException's are different from STL exceptions.
STL exceptions are thrown created on the stack, like

throw std::overflow_error();

Instead CException's must be thrown created on the heap, using 'new' (and
pointers).

Note also that you may want to use DECLARE_DYNAMIC( CYourException ) if you
derive an exception from CException.

You may read 'afx.h' header file for examples of MFC exceptions derived from
CException (or from CSimpleException).

HTH,
Giovanni

Doug Harrison [MVP]

unread,
Apr 8, 2008, 1:51:20 PM4/8/08
to
On Tue, 8 Apr 2008 06:54:40 -0700 (PDT), bamfor...@googlemail.com
wrote:

>Hello all, I'm having a problem creating a class derived from


>CException in VS2005. Here's the class.:
>
>class CIndexException : public CException
>{
>public:
> CIndexException (const CIndexException & oSourceObject) :
>m_pszMessage(oSourceObject.m_pszMessage) {};
> CIndexException & operator = (const CIndexException & oSourceObject)
> {
> m_pszMessage = oSourceObject.m_pszMessage;
> return *this;
> };
>
> CIndexException () : CException(), m_pszMessage(0) {};
> CIndexException (char * pszError = 0, bool bAutoDelete = true) :
>CException(bAutoDelete), m_pszMessage(pszError) {};

Those are both default constructors, and you can usefully have at most one
in a class. Also, you're not making a copy of the string, which means its
lifetime must exceed that of the exception object, which ain't gonna work
for a non-static local char array. So that's pretty dangerous. Finally, you
should be using const char*.

> const char * GetMessage() { return m_pszMessage; }
>protected:
> char * m_pszMessage;
>};
>
>
>The build errors I'm getting are as follows:
>Error 2 error C2248: 'CObject::CObject' : cannot access private member
>declared in class 'CObject' c:\program files\microsoft visual studio
>8\vc\atlmfc\include\afx.h 898
>Error 4 error C2248: 'CObject::CObject' : cannot access private member
>declared in class 'CObject' c:\program files\microsoft visual studio
>8\vc\atlmfc\include\afx.h 898
>
>
>I introduced the copy and assignment constructors thinking they would
>remove the errors but they haven't. Would appreciate any help/
>suggestions to get this working.

The CObject class is not copyable, and you shouldn't try to make classes
you derive from it copyable. You don't need to, since the CException way is
to throw pointers to CException objects created with new. So get rid of the
copy ctor and assignment operator. For a correct implementation of a class
derived from CException, see MfcGenericException here:

http://members.cox.net/doug_web/eh.htm#Q6

Note the CString member variable to hold the error message (fixes your
lifetime issue) and the function GetErrorMessage, which overrides the
CException virtual function. You can still write your GetMessage function
for your own convenience, but you /must/ override GetErrorMessage so that
when your CIndexException* is caught as a CException*, the error message
will be available. Of course, you should derive your own class from
MfcGenericException along the same lines as MfcStdException.

--
Doug Harrison
Visual C++ MVP

bamfor...@googlemail.com

unread,
Apr 10, 2008, 6:41:42 AM4/10/08
to
Gents, many thanks for all your replies. Your posts have helped me to
sort the problem out.
0 new messages