RTTI and DYNAMIC

DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC are used in conjunction to give runtime type identification ability to a class object.

DECLARE_DYNAMIC

This macro adds the ability to access run-time information about an object's class when deriving a class from CObject.
Syntax: DECLARE_DYNAMIC(class_name )
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 DECLARE_DYNAMIC is included in the class declaration, then IMPLEMENT_DYNAMIC must be included in the class implementation.

IMPLEMENT_DYNAMIC

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

Demo App

RUNTIME_CLASS macro and the CObject::IsKindOf function is used to determine the parent class name of an objects at run time. For example we have a drawing application and this uses an abstruct class interface called CDrawObj to draw any shape. We have given user to add custom shapes through library. This is to extend the drawing facility. User should derive a custom class from CDrawObj and should define Draw() function. User can pass any object pointer of any type and application might crash while calling Draw() directly. Thus application should validate the object if it is derived from CDrawObj and then it should invoke Draw(). In this application we are checking user provided object if these are kind of CDrawObj.

#include <afx.h>
CWinApp theApp;

using namespace std;

class CDrawObj : public CObject
{
    virtual void Draw(void) = 0;
  DECLARE_DYNAMIC(CDrawObj)
};
IMPLEMENT_DYNAMIC( CDrawObj, CObject )

/* This is user side implementation in library */
class CRectangle : public CDrawObj
{
    virtual void Draw(void);
  DECLARE_DYNAMIC(CRectangle)
};
IMPLEMENT_DYNAMIC( CRectangle, CDrawObj )
void CRectangle::Draw(void)
{
  cout << "Draw Rect";
}
class CCircle : public CDrawObj
{
    virtual void Draw(void);
  DECLARE_DYNAMIC(CCircle)
};
IMPLEMENT_DYNAMIC( CCircle, CDrawObj )
void CCircle::Draw(void)
{
  cout << "Draw Circle";
}
CObject *GetObjectFromUser(char *ClassName)
{
  if(strcmp(ClassName, "CRectangle") == 0) 
  return new CRectangle();
  else  if(strcmp(ClassName, "CCircle") == 0)
  return new CCircle();
}
/* Above section is in user side library */

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
  /* initialize MFC and print and error on failure */
  if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
  {
  cerr << _T("Fatal Error: MFC initialization failed") << endl;
  return 1;
  }
  CObject *obj = GetObjectFromUser("CRectangle");
  cout << "CRectangle is IsKindOf CDrawObj " << obj->IsKindOf(RUNTIME_CLASS(CDrawObj)) << endl;
  cout << "CRectangle is IsKindOf CObject " << obj->IsKindOf(RUNTIME_CLASS(CObject)) << endl;    

  CObject *obj1 = GetObjectFromUser("CCircle");
  cout << "CRectangle is IsKindOf CDrawObj " << obj1->IsKindOf(RUNTIME_CLASS(CDrawObj)) << endl;
  cout << "CRectangle is IsKindOf CObject " << obj1->IsKindOf(RUNTIME_CLASS(CObject)) << endl;

  return 1;
}

Output

CRectangle is IsKindOf CDrawObj 1
CRectangle is IsKindOf CObject 1
CRectangle is IsKindOf CDrawObj 1
CRectangle is IsKindOf CObject 1

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#