Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
636 views
in Technique[技术] by (71.8m points)

c++ - Why is DECLARE_DYNAMIC & IMPLEMENT_DYNAMIC nessary for DYNAMIC_DOWNCAST?

I have two classes:

/*Switch.h*/
    class CSwitch : public CDeviceEntity {}
/*EndSystem.h*/
    class CEndSystem : public CDeviceEntity {}

but when I use:

CDeviceEntity* dev = NULL;
dev = topo->headList[i]->node;
if ( DYNAMIC_DOWNCAST( CEndSystem, dev ) != NULL ) {}

"DYNAMIC_DOWNCAST" always returns not NULL while dev is kind of class CEndSystem or class CSwitch.

If use:

/*Switch.h*/
    class CSwitch : public CDeviceEntity { DECLARE_DYNAMIC(CSwitch) } 
    and
/*Switch.cpp*/
    IMPLEMENT_DYNAMIC(CSwitch, CDeviceEntity)
/*EndSystem.h*/
    class CEndSystem : public CDeviceEntity { DECLARE_DYNAMIC(CEndSystem) }
    and
/*EndSystem.cpp*/
    IMPLEMENT_DYNAMIC(CEndSystem, CDeviceEntity)

"DYNAMIC_DOWNCAST" returns NULL or not NULL according to class CEndSystem or class CSwitch.

Why "DECLARE_DYNAMIC" and "IMPLEMENT_DYNAMIC" are nessary for "DYNAMIC_DOWNCAST"?

/*Algorithm.h*/
static int getESNum();

/*Algorithm.cpp*/
int CAlgorithm::getESNum()
{
    int count = 0;
    CDeviceEntity* dev = NULL;
    for (int i = 0; i < topo->nodeNum; i++)
    {
        dev = topo->headList[i]->node;
        if ( DYNAMIC_DOWNCAST( CEndSystem, dev ) != NULL )
        {
            count++;
        }
    }

    return count;
}

/*Algorithm.h*/
static int getSWNum();

/*Algorithm.cpp*/
int CAlgorithm::getSWNum()
{
    int count = 0;
    CDeviceEntity* dev = NULL;
    for (int i = 0; i < topo->nodeNum; i++)
    {
        dev = topo->headList[i]->node;
        if ( DYNAMIC_DOWNCAST(CSwitch, dev) != NULL )
        {
            count++;
        }
    }

    return count;
}

And the functions are called in serialization when saving the document.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

DYNAMIC_DOWNCAST is a throw back to how you used to have to do dynamic casting before RTTI information was available from the compiler. The casting information is created using the macros DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC which use the class CRuntimeClass to decide if the cast is valid.

DYNAMIC_DOWNCAST simply does this:

CObject* AFX_CDECL AfxDynamicDownCast(CRuntimeClass* pClass, CObject* pObject)
{
    if (pObject != NULL && pObject->IsKindOf(pClass))
        return pObject;
    else
        return NULL;
}

The DECLARE_DYNAMIC macro adds this code:

#define DECLARE_DYNAMIC(class_name) 
protected: 
    static CRuntimeClass* PASCAL _GetBaseClass(); 
public: 
    static const CRuntimeClass class##class_name; 
    static CRuntimeClass* PASCAL GetThisClass(); 
    virtual CRuntimeClass* GetRuntimeClass() const; 

Add IMPLEMENT_DYNAMIC adds this code:

#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) 
CRuntimeClass* PASCAL class_name::_GetBaseClass() 
    { return RUNTIME_CLASS(base_class_name); } 
AFX_COMDAT const CRuntimeClass class_name::class##class_name = { 
    #class_name, sizeof(class class_name), wSchema, pfnNew, 
        &class_name::_GetBaseClass, NULL, class_init }; 
CRuntimeClass* PASCAL class_name::GetThisClass() 
    { return _RUNTIME_CLASS(class_name); } 
CRuntimeClass* class_name::GetRuntimeClass() const 
    { return _RUNTIME_CLASS(class_name); }

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) 
    IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL)

I imagine few people still use this for new projects, instead preferring the C++ standard dynamic_cast<> call (along with static_cast and reinterpret_cast).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...