CObject Class

CRACK THE INTERVIEW


The principal base class for the Microsoft Foundation Class Library.

class AFX_NOVTABLE CObject

Remarks

It serves as the root not only for library classes such as CFile and CObList, but also for the classes that you write. CObject provides basic services, including

  • Serialization support
  • Run-time class information
  • Object diagnostic output
  • Compatibility with collection classes

Note that CObject does not support multiple inheritance. Your derived classes can have only one CObject base class, and that CObject must be leftmost in the hierarchy. It is permissible, however, to have structures and non-CObject-derived classes in right-hand multiple-inheritance branches.

You will realize major benefits from CObject derivation if you use some of the optional macros in your class implementation and declarations.

The first-level macros, DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC, permit run-time access to the class name and its position in the hierarchy. This, in turn, allows meaningful diagnostic dumping.

The second-level macros, DECLARE_SERIAL and IMPLEMENT_SERIAL, include all the functionality of the first-level macros, and they enable an object to be "serialized" to and from an "archive."

For information about deriving Microsoft Foundation classes and C++ classes in general and using CObject, see Using CObject and Serialization.

Using CObject

CObject is the root base class for most of the Microsoft Foundation Class Library (MFC). The CObject class contains many useful features that you may want to incorporate into your own program objects, including serialization support, run-time class information, and object diagnostic output. If you derive your class from CObject, your class can exploit these CObject features.

CObject Members

Construction

CObject

Default constructor.

CObject

Copy constructor.

operator delete

Special delete operator.

operator new

Special new operator.

Diagnostics

AssertValid

Validates this object's integrity.

Dump

Produces a diagnostic dump of this object.

Serialization

IsSerializable

Tests to see whether this object can be serialized.

Serialize

Loads or stores an object from/to an archive.

Miscellaneous

GetRuntimeClass

Returns the CRuntimeClass structure corresponding to this object's class.

IsKindOf

Tests this object's relationship to a given class.

CObject::AssertValid

Validates this object's integrity.

virtual void AssertValid( ) const;

Remarks

AssertValid performs a validity check on this object by checking its internal state. In the Debug version of the library, AssertValid may assert and thus terminate the program with a message that lists the line number and filename where the assertion failed.

When you write your own class, you should override the AssertValid function to provide diagnostic services for yourself and other users of your class. The overridden AssertValid usually calls the AssertValid function of its base class before checking data members unique to the derived class.

Because AssertValid is a const function, you are not permitted to change the object state during the test. Your own derived class AssertValid functions should not throw exceptions but rather should assert whether they detect invalid object data.

The definition of "validity" depends on the object's class. As a rule, the function should perform a "shallow check." That is, if an object contains pointers to other objects, it should check to see whether the pointers are not null, but it should not perform validity testing on the objects referred to by the pointers.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

Copy Code

// example for CObject::AssertValid

void CAge::AssertValid() const

{

CObject::AssertValid();

ASSERT( m_years > 0 );

ASSERT( m_years <>

}

CObject::CObject

These functions are the standard CObject constructors.

CObject( );
CObject( const CObject& objectSrc );

Parameters

objectSrc

A reference to another CObject

Remarks

The default version is automatically called by the constructor of your derived class.

If your class is serializable (it incorporates the IMPLEMENT_SERIAL macro), then you must have a default constructor (a constructor with no arguments) in your class declaration. If you do not need a default constructor, declare a private or protected "empty" constructor. For more information, see Using CObject.

The standard C++ default class copy constructor does a member-by-member copy. The presence of the private CObject copy constructor guarantees a compiler error message if the copy constructor of your class is needed but not available. You must therefore provide a copy constructor if your class requires this capability.

Example

See CObList::CObList for a listing of the CAge class used in the CObject examples.

Copy Code

// Create a CAge object using the default constructor.
CAge age1;
 
// Create a CAge object using the copy constructor.
CAge age2( age1 );

CObject::Dump

Dumps the contents of your object to a CDumpContext object.

virtual void Dump(
   CDumpContext& dc 
) const;

Parameters

dc

The diagnostic dump context for dumping, usually afxDump.

Remarks

When you write your own class, you should override the Dump function to provide diagnostic services for yourself and other users of your class. The overridden Dump usually calls the Dump function of its base class before printing data members unique to the derived class. CObject::Dump prints the class name if your class uses the IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL macro.

NoteNote

Your Dump function should not print a newline character at the end of its output.

Dump calls make sense only in the Debug version of the Microsoft Foundation Class Library. You should bracket calls, function declarations, and function implementations with #ifdef _DEBUG/#endif statements for conditional compilation.

Since Dump is a const function, you are not permitted to change the object state during the dump.

The CDumpContext insertion (<<) operator calls Dump when a CObject pointer is inserted.

Dump permits only "acyclic" dumping of objects. You can dump a list of objects, for example, but if one of the objects is the list itself, you will eventually overflow the stack.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

Copy Code

// example for CObject::Dump
void CAge::Dump( CDumpContext &dc ) const
 {
 CObject::Dump( dc );
 dc << "Age = " <<>
 }

CObject::GetRuntimeClass

Returns the CRuntimeClass structure corresponding to this object's class.

virtual CRuntimeClass* GetRuntimeClass( ) const;

Return Value

A pointer to the CRuntimeClass structure corresponding to this object's class; never NULL.

Remarks

There is one CRuntimeClass structure for each CObject-derived class. The structure members are as follows:

  • LPCSTR m_lpszClassName A null-terminated string containing the ASCII class name.
  • int m_nObjectSize The size of the object, in bytes. If the object has data members that point to allocated memory, the size of that memory is not included.
  • UINT m_wSchema The schema number ( – 1 for nonserializable classes). See the IMPLEMENT_SERIAL macro for a description of schema number.
  • CObject* ( PASCAL* m_pfnCreateObject )( ) A function pointer to the default constructor that creates an object of your class (valid only if the class supports dynamic creation; otherwise, returns NULL).
  • CRuntimeClass* ( PASCAL* m_pfn_GetBaseClass )( ) If your application is dynamically linked to the AFXDLL version of MFC, a pointer to a function that returns the CRuntimeClass structure of the base class.
  • CRuntimeClass* m_pBaseClass If your application is statically linked to MFC, a pointer to the CRuntimeClass structure of the base class.

This function requires use of the IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE, or IMPLEMENT_SERIAL macro in the class implementation. You will get incorrect results otherwise.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

Copy Code

// example for CObject::GetRuntimeClass

CAge a(21);

CRuntimeClass* prt = a.GetRuntimeClass();

ASSERT( strcmp( prt->m_lpszClassName, "CAge" ) == 0 );

CObject::IsKindOf

Tests this object's relationship to a given class.

BOOL IsKindOf(
   const CRuntimeClass* pClass 
) const;

Parameters

pClass

A pointer to a CRuntimeClass structure associated with your CObject-derived class.

Return Value

Nonzero if the object corresponds to the class; otherwise 0.

Remarks

This function tests pClass to see if (1) it is an object of the specified class or (2) it is an object of a class derived from the specified class. This function works only for classes declared with the DECLARE_DYNAMIC, DECLARE_DYNCREATE, or DECLARE_SERIAL macro.

Do not use this function extensively because it defeats the C++ polymorphism feature. Use virtual functions instead.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

Copy Code

// example for CObject::IsKindOf
CAge a(21);  // Must use IMPLEMENT_DYNAMIC, IMPLEMENT _DYNCREATE, or
             // IMPLEMENT_SERIAL
ASSERT( a.IsKindOf( RUNTIME_CLASS( CAge ) ) );
ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );

CObject::IsSerializable

Tests whether this object is eligible for serialization.

BOOL IsSerializable( ) const;

Return Value

Nonzero if this object can be serialized; otherwise 0.

Remarks

For a class to be serializable, its declaration must contain the DECLARE_SERIAL macro, and the implementation must contain the IMPLEMENT_SERIAL macro.

NoteNote

Do not override this function.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

Copy Code

// example for CObject::IsSerializable

CAge a(21);

ASSERT( a.IsSerializable() );

CObject::Serialize

Reads or writes this object from or to an archive.

virtual void Serialize(
   CArchive& ar 
);

Parameters

ar

A CArchive object to serialize to or from.

Remarks

You must override Serialize for each class that you intend to serialize. The overridden Serialize must first call the Serialize function of its base class.

You must also use the DECLARE_SERIAL macro in your class declaration, and you must use the IMPLEMENT_SERIAL macro in the implementation.

Use CArchive::IsLoading or CArchive::IsStoring to determine whether the archive is loading or storing.

Serialize is called by CArchive::ReadObject and CArchive::WriteObject. These functions are associated with the CArchive insertion operator (<<) and extraction operator (>>).

For serialization examples, see the article Serialization: Serializing an Object.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

Copy Code

// example for CObject::Serialize
void CAge::Serialize( CArchive& ar )
 {
 CObject::Serialize( ar );
     if( ar.IsStoring() )
     ar <<>
     else
     ar >> m_years;
 }

DECLARE_DYNAMIC

Adds the ability to access run-time information about an object's class when deriving a class from CObject.

DECLARE_DYNAMIC(class_name )

Parameters

class_name

The actual name of the class.

Remarks

Add the DECLARE_DYNAMIC macro to the header (.h) module for the class, then include that module in all .cpp modules that need access to objects of this class.

If you use the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC macros as described, you can then use the RUNTIME_CLASS macro and the CObject::IsKindOf function to determine the class of your objects at run time.

If DECLARE_DYNAMIC is included in the class declaration, then IMPLEMENT_DYNAMIC must be included in the class implementation.

IMPLEMENT_DYNAMIC

IMPLEMENT_DYNAMIC( class_name, base_class_name )

Parameters

class_name

The actual name of the class (not enclosed in quotation marks).

base_class_name

The name of the base class (not enclosed in quotation marks).

Remarks

Generates the C++ code necessary for a dynamic CObject-derived class with run-time access to the class name and position within the hierarchy. Use the IMPLEMENT_DYNAMIC macro in a .CPP module, then link the resulting object code only once.

For more information, see in Visual C++ Programmer’s Guide.

Example

// CAge.h
class CAge : public CObject
{
     int num;
public:
     DECLARE_DYNAMIC(CAge)
};
 
//==============
// CAge.cpp
#include "stdafx.h"
#include "CAge.h"
 
IMPLEMENT_DYNAMIC(CAge, CObject)
 

DECLARE_SERIAL

DECLARE_SERIAL( class_name )

Parameters

class_name

The actual name of the class (not enclosed in quotation marks).

Remarks

DECLARE_SERIAL generates the C++ header code necessary for a CObject-derived class that can be serialized. Serialization is the process of writing or reading the contents of an object to and from a file.

Use the DECLARE_SERIAL macro in a .H module, then include that module in all .CPP modules that need access to objects of this class.

If DECLARE_SERIAL is included in the class declaration, then IMPLEMENT_SERIAL must be included in the class implementation.

The DECLARE_SERIAL macro includes all the functionality of DECLARE_DYNAMIC and DECLARE_DYNCREATE.

You can use the AFX_API macro to automatically export the CArchive extraction operator for classes that use the DECLARE_SERIAL and IMPLEMENT_SERIAL macros. Bracket the class declarations (located in the .H file) with the following code:

#undef AFX_API
#define AFX_API AFX_EXT_CLASS
 
 
#undef AFX_API
#define AFX_API

For more information on the DECLARE_SERIAL macro, see in Visual C++ Programmer’s Guide.

Example

class CMyClass: public CObject
{
public:
   CMyClass();
   void Serialize( CArchive& archive );
 
   DECLARE_SERIAL(CMyClass)
};
 
 
 

IMPLEMENT_SERIAL

IMPLEMENT_SERIAL( class_name, base_class_name, wSchema )

Parameters

class_name

The actual name of the class (not enclosed in quotation marks).

base_class_name

The name of the base class (not enclosed in quotation marks).

wSchema

A UINT “version number” that will be encoded in the archive to enable a deserializing program to identify and handle data created by earlier program versions. The class schema number must not be –1.

Remarks

Generates the C++ code necessary for a dynamic CObject-derived class with run-time access to the class name and position within the hierarchy. Use the IMPLEMENT_SERIAL macro in a .CPP module; then link the resulting object code only once.

You can use the AFX_API macro to automatically export the CArchive extraction operator for classes that use the DECLARE_SERIAL and IMPLEMENT_SERIAL macros. Bracket the class declarations (located in the .H file) with the following code:

#undef AFX_API
#define AFX_API AFX_EXT_CLASS
 
 
#undef AFX_API
#define AFX_API

For more information, see the in Visual C++ Programmer’s Guide.

Example

// MyClass.cpp
#include "stdafx.h"
#include "MyClass.h"
 
IMPLEMENT_SERIAL( CMyClass, CObject, VERSIONABLE_SCHEMA | 2 )
 

CObject::IsKindOf

BOOL IsKindOf( const CRuntimeClass* pClass ) const;

Return Value

Nonzero if the object corresponds to the class; otherwise 0.

Parameters

pClass

A pointer to a CRuntimeClass structure associated with your CObject-derived class.

Remarks

Tests pClass to see if (1) it is an object of the specified class or (2) it is an object of a class derived from the specified class. This function works only for classes declared with the DECLARE_DYNAMIC or DECLARE_SERIAL macro.

Do not use this function extensively because it defeats the C++ polymorphism feature. Use virtual functions instead.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

// example for CObject::IsKindOf
CAge a(21); // Must use IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL
ASSERT( a.IsKindOf( RUNTIME_CLASS( CAge ) ) );
ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );
 

CObject::GetRuntimeClass

virtual CRuntimeClass* GetRuntimeClass( ) const;

Return Value

A pointer to the CRuntimeClass structure corresponding to this object’s class; never NULL.

Remarks

There is one CRuntimeClass structure for each CObject-derived class. The structure members are as follows:

  • LPCSTR m_lpszClassName A null-terminated string containing the ASCII class name.
  • int m_nObjectSize The size of the object, in bytes. If the object has data members that point to allocated memory, the size of that memory is not included.
  • UINT m_wSchema The schema number ( – 1 for nonserializable classes). See the IMPLEMENT_SERIAL macro for a description of schema number.
  • CObject* ( PASCAL* m_pfnCreateObject )( ) A function pointer to the default constructor that creates an object of your class (valid only if the class supports dynamic creation; otherwise, returns NULL).
  • CRuntimeClass* ( PASCAL* m_pfn_GetBaseClass )( ) If your application is dynamically linked to the AFXDLL version of MFC, a pointer to a function that returns the CRuntimeClass structure of the base class.
  • CRuntimeClass* m_pBaseClass If your application is statically linked to MFC, a pointer to the CRuntimeClass structure of the base class.

Feature Only in Professional and Enterprise Editions Static linking to MFC is supported only in Visual C++ Professional and Enterprise Editions. For more information, see .

This function requires use of the IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL macro in the class implementation. You will get incorrect results otherwise.

Example

See CObList::CObList for a listing of the CAge class used in all CObject examples.

// example for CObject::GetRuntimeClass

CAge a(21);

CRuntimeClass* prt = a.GetRuntimeClass();

ASSERT( strcmp( prt->m_lpszClassName, "CAge" ) == 0 );

 
 

RUNTIME_CLASS

RUNTIME_CLASS( class_name )

Parameters

class_name

The actual name of the class (not enclosed in quotation marks).

Remarks

Use this macro to get the run-time class structure from the name of a C++ class.

RUNTIME_CLASS returns a pointer to a CRuntimeClass structure for the class specified by class_name. Only CObject-derived classes declared with DECLARE_DYNAMIC, DECLARE_DYNCREATE, or DECLARE_SERIAL will return pointers to a CRuntimeClass structure.

For more information, see in Visual C++ Programmer’s Guide.

Example

// example for RUNTIME_CLASS
CRuntimeClass* prt = RUNTIME_CLASS( CAge );
ASSERT( lstrcmp( prt->m_lpszClassName, "CAge" )  == 0 );

What do you want to do?

Deriving a Class from CObject

This article describes the minimum steps necessary to derive a class from CObject. Other CObject class articles describe the steps needed to take advantage of specific CObject features, such as serialization and diagnostic debugging support.

In the discussions of CObject, the terms "interface file" and "implementation file" are used frequently. The interface file (often called the header file, or .H file) contains the class declaration and any other information needed to use the class. The implementation file (or .CPP file) contains the class definition as well as the code that implements the class member functions. For example, for a class named CPerson, you would typically create an interface file named PERSON.H and an implementation file named PERSON.CPP. However, for some small classes that will not be shared among applications, it is sometimes easier to combine the interface and implementation into a single .CPP file.

You can choose from four levels of functionality when deriving a class from CObject:

· Basic functionality: No support for run-time class information or serialization but includes diagnostic memory management.

· Basic functionality plus support for run-time class information.

· Basic functionality plus support for run-time class information and dynamic creation.

· Basic functionality plus support for run-time class information, dynamic creation, and serialization.

Classes designed for reuse (those that will later serve as base classes) should at least include run-time class support and serialization support, if any future serialization need is anticipated.

You choose the level of functionality by using specific declaration and implementation macros in the declaration and implementation of the classes you derive from CObject.

The following table shows the relationship among the macros used to support serialization and run-time information.

Macros Used for Serialization and Run-Time Information

Macro used

CObject::IsKindOf

CRuntimeClass:: CreateObject

CArchive::operator>> CArchive::operator<<

Basic CObject functionality

No

No

No

DECLARE_DYNAMIC

Yes

No

No

DECLARE_DYNCREATE

Yes

Yes

No

DECLARE_SERIAL

Yes

Yes

Yes

To use basic CObject functionality

· Use the normal C++ syntax to derive your class from CObject (or from a class derived from CObject).

The following example shows the simplest case, the derivation of a class from CObject:

Copy Code

class CPerson : public CObject 
{
    // add CPerson-specific members and functions... 
}

Normally, however, you may want to override some of CObject's member functions to handle the specifics of your new class. For example, you may usually want to override the Dump function of CObject to provide debugging output for the contents of your class. For details on how to override Dump, see the article Diagnostics: Dumping Object Contents. You may also want to override the AssertValid function of CObject to provide customized testing to validate the consistency of the data members of class objects. For a description of how to override AssertValid, see MFC ASSERT_VALID and CObject::AssertValid.

The article Specifying Levels of Functionality describes how to specify other levels of functionality, including run-time class information, dynamic object creation, and serialization.

Specifying Levels of Functionality

This article describes how to add the following levels of functionality to your CObject-derived class:

· Run-time class information

· Dynamic creation support

· Serialization support

For a general description of CObject functionality, see the article Deriving a Class from CObject.

To add run-time class information

1. Derive your class from CObject, as described in the Deriving a Class from CObject article.

2. Use the DECLARE_DYNAMIC macro in your class declaration, as shown here:

Copy Code

class CPerson : public CObject
{
    DECLARE_DYNAMIC( CPerson )
 
    // rest of class declaration follows...
};

3. Use the IMPLEMENT_DYNAMIC macro in the implementation file (.CPP) of your class. This macro takes as arguments the name of the class and its base class, as follows:

Copy Code

IMPLEMENT_DYNAMIC( CPerson, CObject )

NoteNote

Always put IMPLEMENT_DYNAMIC in the implementation file (.CPP) for your class. The IMPLEMENT_DYNAMIC macro should be evaluated only once during a compilation and therefore should not be used in an interface file (.H) that could potentially be included in more than one file.

To add dynamic creation support

1. Derive your class from CObject.

2. Use the DECLARE_DYNCREATE macro in the class declaration.

3. Define a constructor with no arguments (a default constructor).

4. Use the IMPLEMENT_DYNCREATE macro in the class implementation file.

To add serialization support

1. Derive your class from CObject.

2. Override the Serialize member function.

NoteNote

If you call Serialize directly, that is, you do not want to serialize the object through a polymorphic pointer, omit steps 3 through 5.

3. Use the DECLARE_SERIAL macro in the class declaration.

4. Define a constructor with no arguments (a default constructor).

5. Use the IMPLEMENT_SERIAL macro in the class implementation file.

NoteNote

A "polymorphic pointer" points to an object of a class (call it A) or to an object of any class derived from A (say, B). To serialize through a polymorphic pointer, the framework must determine the run-time class of the object it is serializing (B), since it might be an object of any class derived from some base class (A).

Accessing Run-Time Class Information

This article explains how to access information about the class of an object at run time.

NoteNote

MFC does not use the Run-Time Type Information (RTTI) support introduced in Visual C++ 4.0.

If you have derived your class from CObject and used the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC, the DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE, or the DECLARE_SERIAL and IMPLEMENT_SERIAL macros explained in the article Deriving a Class from CObject, the CObject class has the ability to determine the exact class of an object at run time.

This ability is most useful when extra type checking of function arguments is needed and when you must write special-purpose code based on the class of an object. However, this practice is not usually recommended because it duplicates the functionality of virtual functions.

The CObject member function IsKindOf can be used to determine if a particular object belongs to a specified class or if it is derived from a specific class. The argument to IsKindOf is a CRuntimeClass object, which you can get using the RUNTIME_CLASS macro with the name of the class.

To use the RUNTIME_CLASS macro

· Use RUNTIME_CLASS with the name of the class, as shown here for the class CObject:

Copy Code

CRuntimeClass* pClass = RUNTIME_CLASS( CObject );

You will rarely need to access the run-time class object directly. A more common use is to pass the run-time class object to the IsKindOf function, as shown in the next procedure. The IsKindOf function tests an object to see if it belongs to a particular class.

To use the IsKindOf function

1. Make sure the class has run-time class support. That is, the class must have been derived directly or indirectly from CObject and used the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC, the DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE, or the DECLARE_SERIAL and IMPLEMENT_SERIAL macros explained in the article Deriving a Class from CObject.

2. Call the IsKindOf member function for objects of that class, using the RUNTIME_CLASS macro to generate the CRuntimeClass argument, as shown here:

Copy Code

// in .H file
class CPerson : public CObject
{
    DECLARE_DYNAMIC( CPerson )
public:
    CPerson(){};
 
    // other declaration 
};
 
// in .CPP file
IMPLEMENT_DYNAMIC( CPerson, CObject )
 
void SomeFunction(void)
{
   CObject* pMyObject = new CPerson;
 
   if(pMyObject->IsKindOf( RUNTIME_CLASS( CPerson ) ) )
   {
      //if IsKindOf is true, then cast is all right
      CPerson* pmyPerson = (CPerson*) pMyObject ;
      ...
      delete pmyPerson;
   }
...
   delete [MyObject];
}

NoteNote

IsKindOf returns TRUE if the object is a member of the specified class or of a class derived from the specified class. IsKindOf does not support multiple inheritance or virtual base classes, although you can use multiple inheritance for your derived Microsoft Foundation classes if necessary.

One use of run-time class information is in the dynamic creation of objects. This process is discussed in the article Dynamic Object Creation.

For more detailed information on serialization and run-time class information, see the articles Files in MFC and Serialization.

Dynamic Object Creation

This article explains how to create an object dynamically at run time. The procedure uses run-time class information, as discussed in the article Accessing Run-Time Class Information.

To dynamically create an object given its run-time class

· Use the following code to dynamically create an object by using the CreateObject function of the CRuntimeClass. Note that on failure, CreateObject returns NULL instead of raising an exception:

Copy Code

CRuntimeClass* pRuntimeClass = RUNTIME_CLASS( CMyClass );
CObject* pObject = pRuntimeClass->CreateObject();
ASSERT( pObject->IsKindOf( RUNTIME_CLASS( CMyClass ) ) );

Object Dump Customization

This topic applies to:

Visual Studio Edition

Visual Basic

C#

C++

J#

Express

No

No

Native

No

Standard

No

No

Native

No

Pro/Team

No

No

Native

No

When you derive a class from CObject, you can override the Dump member function to provide additional information when you use DumpAllObjectsSince to dump objects to the Output window.

The Dump function writes a textual representation of the object's member variables to a dump context (CDumpContext). The dump context is similar to an I/O stream. You can use the append operator (<<) to send data to a CDumpContext.

When you override the Dump function, you should first call the base class version of Dump to dump the contents of the base class object. Then output a textual description and value for each member variable of your derived class.

The declaration of the Dump function looks like this:

Copy Code

class CPerson : public CObject

{

public:

#ifdef _DEBUG

virtual void Dump( CDumpContext& dc ) const;

#endif

CString m_firstName;

CString m_lastName;

// And so on...

};

Because object dumping only makes sense when you are debugging your program, the declaration of the Dump function is bracketed with an #ifdef _DEBUG / #endif block.

In the following example, the Dump function first calls the Dump function for its base class. It then writes a short description of each member variable along with the member's value to the diagnostic stream.

Copy Code

#ifdef _DEBUG

void CPerson::Dump( CDumpContext& dc ) const

{

// Call the base class function first.

CObject::Dump( dc );

// Now do the stuff for our specific class.

dc << "last name: " <<>

<< "first name: " <<>

}

#endif

You must supply a CDumpContext argument to specify where the dump output will go. The Debug version of MFC supplies a predefined CDumpContext object named afxDump that sends output to the debugger.

Copy Code

CPerson* pMyPerson = new CPerson;

// Set some fields of the CPerson object.

//...

// Now dump the contents.

#ifdef _DEBUG

pMyPerson->Dump( afxDump );

#endif

No comments: