MFC ASSERT_VALID and CObject::AssertValid

This topic applies to:

Edition

Visual Basic

C#

F#

C++

Web Developer

Express

Topic does not apply Topic does not apply Topic does not apply

Native only

Topic does not apply

Pro, Premium, and Ultimate

Topic does not apply Topic does not apply Topic does not apply

Native only

Topic does not apply

The CObject::AssertValid method provides run-time checks of the internal state of an object. Although you are not required to override AssertValid when you derive your class from CObject, you can make your class more reliable by doing this. AssertValid should perform assertions on all the object's member variables to verify that they contain valid values. For example, it should check that pointer member variables are not NULL.

The following example shows how to declare an AssertValid function:

class CPerson : public CObject
{
protected:
    CString m_strName;
    float   m_salary;
public:
#ifdef _DEBUG
    // Override
    virtual void AssertValid() const;
#endif
    // ...
};

When you override AssertValid, call the base class version of AssertValid before you perform your own checks. Then use the ASSERT macro to check the members unique to your derived class, as shown here:

#ifdef _DEBUG
void CPerson::AssertValid() const
{
    // Call inherited AssertValid first.
    CObject::AssertValid();

    // Check CPerson members...
    // Must have a name.
    ASSERT( !m_strName.IsEmpty());
    // Must have an income.
    ASSERT( m_salary > 0 );
}
#endif

If any of your member variables store objects, you can use the ASSERT_VALID macro to test their internal validity (if their classes override AssertValid).

For example, consider a class CMyData, which stores a CObList in one of its member variables. The CObList variable, m_DataList, stores a collection of CPerson objects. An abbreviated declaration of CMyData looks like this:

class CMyData : public CObject
{
    // Constructor and other members ...
    protected:
        CObList* m_pDataList;
    // Other declarations ...
    public:
#ifdef _DEBUG
        // Override:
        virtual void AssertValid( ) const;
#endif
    // And so on ...
};

The AssertValid override in CMyData looks like this:

#ifdef _DEBUG
void CMyData::AssertValid( ) const
{
    // Call inherited AssertValid.
    CObject::AssertValid( );
    // Check validity of CMyData members.
    ASSERT_VALID( m_pDataList );
    // ...
}
#endif

CMyData uses the AssertValid mechanism to test the validity of the objects stored in its data member. The overriding AssertValid of CMyData invokes the ASSERT_VALID macro for its own m_pDataList member variable.

Validity testing does not stop at this level because the class CObList overrides AssertValid too. This override performs additional validity testing on the internal state of the list. Thus, a validity test on a CMyData object leads to additional validity tests for the internal states of the stored CObList list object.

With some more work, you could add validity tests for the CPerson objects stored in the list also. You could derive a class CPersonList from CObList and override AssertValid. In the override, you would call CObject::AssertValid and then iterate through the list, calling AssertValid on each CPerson object stored in the list. The CPerson class shown at the beginning of this topic already overrides AssertValid.

This is a powerful mechanism when you build for debugging. When you subsequently build for release, the mechanism is turned off automatically.

Limitations of AssertValid

Users of an AssertValid function of a given class should realize of the limitations of this function. A triggered assertion indicates that the object is definitely bad and execution will stop. However, a lack of assertion only indicates that no problem was found, but the object is not guaranteed to be good.

See Also

Concepts

MFC Assertions