65.9K
CodeProject is changing. Read more.
Home

CObect , CRuntimeClass and related macros

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (5 votes)

Apr 2, 2007

2 min read

viewsIcon

28912

A project that will dynamically create an object from a class

Introduction

When I was making a project that will dynamically create an object from a class, I decided that the CObject class should be the basis for all classes.

But why was it necessary to make a CObject the base class? I went searching on Code Project. Unfortunately I didn't find an explanation. Rather I created more questions, they are:

  1. Why should CObject be a base class and how we can be facilitate this?
  2. What is CRuntimeClass? What is the RUNTIME_CLASS macro?
  3. What are all these macros:
    • DECLARE_DYNAMIC
    • IMPLEMENT_DYNAMIC
    • DECLARE_DYNCREATE
    • IMPLEMENT_DYNCREATE

I have tried to describe all of them with simple and easy examples. I have even explained the use of some important member functions of these classes and structures. Such as:

  • IsKindOf
  • GetRuntimeClass
  • CreateObject
  • FromName
  • IsDerivedFrom

Answers

  1. If you derive a class from CObject, then you will get this kind of support run-time class information, dynamic creation, and serialization.
  2. CRunitmeClass is a structure and does not have a base class.
    RUNTIME_CLASS: this macro is used to Get the object of run-time class structures from the name of a given class name.
    RUNTIME_CLASS(class_name): the class name should not enclosed in quotation marks. Inside this class, DECLARE_DYNAMIC macro must be used.
  3. See the table. This is not same as MSDN's table:

Screenshot - CObject___CRuntimeClass.jpg
Figure 1

Using the code with examples

If you follow all the examples, it will be easy to grab the total concept.

//In interface file 
//CMyRuntime should be derived from CObject for run time support

class CMyRuntime : public CObject
{
    DECLARE_DYNAMIC(CMyRuntime) // for run time support 

public:
    BOOL ShowName(CString strName);
}; 

class CMyRuntime_Derived : public CMyRuntime
{
    DECLARE_DYNAMIC(CMyRuntime_Derived) // for run time support 

public:
    BOOL ShowNameDrvd(CString strName);
}; 


//In implementation file
IMPLEMENT_DYNAMIC(CMyRuntime, CObject) 

BOOL CMyRuntime::ShowName(CString strName)
{
    AfxMessageBox(strName);
    return TRUE;
} 

IMPLEMENT_DYNAMIC(CMyRuntime_Derived, CMyRuntime)

BOOL CMyRuntime_Derived::ShowNameDrvd(CString strName)
{
    AfxMessageBox(strName);
    return TRUE;
} 

//BOOL RuntimeCkeck(CRuntimeClass *pRTClass)
BOOL RuntimeCkeck(CObject* pObj)
{
    //first use
    // To get class name
    CRuntimeClass *pClass = pObj.GetRuntimeClass();
    LPCSTR className = pClass->m_lpszClassName;

    //or you can use this
    if(strcmp(pRTClass->m_lpszClassName, "CMyRuntime" ) == 0)
    {
        //do whatever
    } 

    //second use
    //To be sure that, is there any relation between this two class 
    //e.g. "CMyRuntime_Derived" is base or child of "CMyRuntime"

    CMyRuntime_Derived pMyruntime;
    BOOL bRTCheck = pMyruntime.IsKindOf(RUNTIME_CLASS(CMyRuntime)); 

    return bRTCheck;
} 

//In any other file 
void AnyFunction()
{
    CMyRuntime_DerivedpObj;
    BOOL bCheck = RuntimeCkeck(&pObj);//check class name is correct or not 

    //BOOL bCheck =
    RuntimeCkeck(RUNTIME_CLASS(CMyRuntime));
}

Up to here all discussion has been about:

  • CObject
  • DECLARE_DYNAMIC
  • IMPLEMENT_DYNAMIC
  • IsKindOf
  • GetRuntimeClass()
  • m_lpszClassName

In the above example you can use the CRuntimeClass::IsDerivedFrom((RUNTIME_CLASS(CMyRuntime)) function, but you can't use CRuntimeClass::CreateObject() , because you did not use the DECLARE_DYNCREATE and the IMPLEMENT_DYNCREATE macro.

Now see the use of CRuntimeClass::CreateObject() function:

//In interface file

class CMyRuntime : public CObject
{
    DECLARE_DYNCREATE(CMyRuntime) // for run time support

public:
    BOOL ShowName(CString strName);
}; 

class CMyRuntime_Derived :public CMyRuntime
{
    DECLARE_DYNCREATE(CMyRuntime_Derived) // for run time support 

public:
    BOOL ShowNameDrvd(CString strName);
}; 

//In implementation file 
CObject* GlobalObjectCreator(CRuntimeClass
                             *pClass)
{
    CObject *pObject = NULL; 

    if(pClass == NULL)
    {
        return pObject;
    }
    //if CMyRuntime_Derived is not derived from CMyRuntime, it will return 0
    BOOL bRelation = pClass->IsDerivedFrom(RUNTIME_CLASS(CMyRuntime)); 

    pObject = pClass->CreateObject();
    if(pObject == NULL)
    {
        AfxMessageBox(_T("Out of memory creating an object "));
    }
    //if you use any other class name instead of CMyRuntime, it will return 0.
    bRelation = pObject->IsKindOf(RUNTIME_CLASS(CMyRuntime)); 

    return pObject;
} 

//----- 

IMPLEMENT_DYNCREATE(CMyRuntime, CObject) 

BOOL CMyRuntime::ShowName(CString strName)
{
    AfxMessageBox(strName);
    return 1;
} 

IMPLEMENT_DYNCREATE(CMyRuntime_Derived, CMyRuntime) 

BOOL CMyRuntime_Derived::ShowNameDrvd(CString strName)
{
    AfxMessageBox(strName); 
    return TRUE;
} 

//In any other file 
void AnyFunction()
{
    CMyRuntime_Derived* pMyRuntime = NULL; 
    pMyRuntime = (CMyRuntime_Derived*)GlobalObjectCreator(RUNTIME_CLASS(
        CMyRuntime_Derived));
    pMyRuntime->ShowName(_T("Hi"));
}

Note: An easy and simple way of learning this is to just copy the code and debug with break point.

Also, I didn't discuss Serialization here, though this is also part of this topic.

If there are any suggestions, requests or problems please inform me.