65.9K
CodeProject 正在变化。 阅读更多。
Home

关于 CObject、CRuntimeClass 和相关宏。

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.72/5 (6投票s)

2007年3月29日

2分钟阅读

viewsIcon

28455

CObject、CRuntimeClass 和相关宏的用途是什么?

引言

当我正在创建一个将动态创建类的对象的项目时,
有人建议所有类的基类都应该是 CObject 类。

但是为了了解为什么需要将 CObject 作为基类。我正在 CodeProject 中搜索。
不幸的是,我没有找到更好的解释。
相反,我创建了更多的问题,它们是 –

1. 为什么 CObject 应该作为基类,我们如何从中受益?
2. 什么是 CRuntimeClass?什么是 RUNTIME_CLASS 宏?
3. 这些宏都是什么 –
DECLARE_DYNAMIC 和 IMPLEMENT_DYNAMIC、DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE。

我尝试用简单易懂的例子来描述它们。

甚至我解释了这些类和结构的一些重要成员函数的使用。
例如 –

IsKindOf、GetRuntimeClass、CreateObject、FromName、IsDerivedFrom。

我之前提出的问题的答案

答 1
如果从 CObject 派生一个类,您将获得此类支持
运行时类信息、动态创建和序列化。

答 2
CRunitmeClass 是一个结构,没有基类。

RUNTIME_CLASS 这个宏用于从给定类名中获取运行时类结构的__object__
RUNTIME_CLASS(class_name)

RUNTIME_CLASS(类名)
//类名不应包含在引号中,并且必须在此类中使用 DECLARE_DYNAMIC 宏。

答 3:请参见表格。这与 MSDN 的表格不同 -

Screenshot - RuntimeTable.jpg

使用带示例的代码

如果您遵循所有示例,那么理解总的概念将很容易

//在接口文件中

//CMyRuntime 应该从 CObject 派生以获得运行时支持

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);
}; 


//在实现文件中

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_Derived pObj;
 BOOL bCheck = RuntimeCkeck(&pObj); //check class name is correct or not 
 //BOOL bCheck = RuntimeCkeck(RUNTIME_CLASS(CMyRuntime));
} 

到目前为止,所有讨论都集中在 -
CObject、DECLARE_DYNAMIC、IMPLEMENT_DYNAMIC、IsKindOf、GetRuntimeClass()。(和 m_lpszClassName)。

在上面的例子中,您可以使用 CRuntimeClass::IsDerivedFrom((RUNTIME_CLASS(CMyRuntime)) 函数
但是
您无法使用 CRuntimeClass::CreateObject() ,
因为您没有使用 DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE 宏。

现在请看 CRuntimeClass::CreateObject() 函数的用法 -


//在接口文件中

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);
}; 


//在实现文件中

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"));
} 

注意

学习这个的简单方法是,只需复制代码并使用断点调试。

重要

这里我没有讨论序列化,这也是这个主题的一部分。

如果有任何建议、请求或任何问题,请告诉我。

关于我

我是 Mahfuzur Rahman (软件工程师)。

© . All rights reserved.