分享
 
 
 

VC6下如何实现通过字符串创建对象

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在编程过程中,有可能遇到想根据传入的字符串创建相应的对象,在VC7下可以实现,VC6下MFC没有实现该功能。

大家首先要明白,MFC中实现动态创建关键是在于CRuntimeClass类,可以参考《深入浅出MFC》,废话少说,先看CRuntimeClass类。

VC7中CRuntimeClass类中增加了如下函数:

struct CRuntimeClass

{

...

// dynamic name lookup and creation

static CRuntimeClass* PASCAL FromName(LPCSTR lpszClassName);

static CRuntimeClass* PASCAL FromName(LPCWSTR lpszClassName);

static CObject* PASCAL CreateObject(LPCSTR lpszClassName);

static CObject* PASCAL CreateObject(LPCWSTR lpszClassName);

...

}

函数定义:

// Runtime class serialization code

CObject* PASCAL CRuntimeClass::CreateObject(LPCSTR lpszClassName)

{

// attempt to find matching runtime class structure

CRuntimeClass* pClass = FromName(lpszClassName);

if (pClass == NULL)

{

// not found, trace a warning for diagnostic purposes

TRACE(traceAppMsg, 0, "Warning: Cannot find %hs CRuntimeClass. Class not defined.\n",

lpszClassName);

return NULL;

}

// attempt to create the object with the found CRuntimeClass

CObject* pObject = pClass->CreateObject();

return pObject;

}

CObject* PASCAL CRuntimeClass::CreateObject(LPCWSTR lpszClassName)

{

USES_CONVERSION;

return CRuntimeClass::CreateObject(W2A(lpszClassName));

}

CRuntimeClass* PASCAL CRuntimeClass::FromName(LPCSTR lpszClassName)

{

CRuntimeClass* pClass;

// search app specific classes

AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

AfxLockGlobals(CRIT_RUNTIMECLASSLIST);

for (pClass = pModuleState->m_classList; pClass != NULL;

pClass = pClass->m_pNextClass)

{

if (lstrcmpA(lpszClassName, pClass->m_lpszClassName) == 0)

{

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

return pClass;

}

}

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

#ifdef _AFXDLL

// search classes in shared DLLs

AfxLockGlobals(CRIT_DYNLINKLIST);

for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;

pDLL = pDLL->m_pNextDLL)

{

for (pClass = pDLL->m_classList; pClass != NULL;

pClass = pClass->m_pNextClass)

{

if (lstrcmpA(lpszClassName, pClass->m_lpszClassName) == 0)

{

AfxUnlockGlobals(CRIT_DYNLINKLIST);

return pClass;

}

}

}

AfxUnlockGlobals(CRIT_DYNLINKLIST);

#endif

return NULL; // not found

}

CRuntimeClass* PASCAL CRuntimeClass::FromName(LPCWSTR lpszClassName)

{

USES_CONVERSION_EX;

LPCSTR pszClassName = W2A_EX(lpszClassName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);

if( pszClassName == NULL )

return NULL;

return CRuntimeClass::FromName( pszClassName );

}

其实在VC6中的CRuntimeClass类的Load函数中就可以发现FromName函数的身影,微软只不过是将其中的部分代码提取出来作为单独的FromName函数,看下面Load函数。

// Runtime class serialization code

CRuntimeClass* PASCAL CRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum)

// loads a runtime class description

{

...

// search app specific classes

AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

AfxLockGlobals(CRIT_RUNTIMECLASSLIST);

for (pClass = pModuleState->m_classList; pClass != NULL;

pClass = pClass->m_pNextClass)

{

if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)

{

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

return pClass;

}

}

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

#ifdef _AFXDLL

// search classes in shared DLLs

AfxLockGlobals(CRIT_DYNLINKLIST);

for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;

pDLL = pDLL->m_pNextDLL)

{

for (pClass = pDLL->m_classList; pClass != NULL;

pClass = pClass->m_pNextClass)

{

if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)

{

AfxUnlockGlobals(CRIT_DYNLINKLIST);

return pClass;

}

}

}

AfxUnlockGlobals(CRIT_DYNLINKLIST);

#endif

TRACE1("Warning: Cannot load %hs from archive. Class not defined.\n",

szClassName);

return NULL; // not found

}

下面看看MFC中动态创建宏和序列化宏:

一.MFC中动态创建宏组:

#define DECLARE_DYNCREATE(class_name)

#define IMPLEMENT_DYNCREATE(class_name, base_class_name)

1.DECLARE_DYNCREATE展开:

protected:

static CRuntimeClass* PASCAL _GetBaseClass();

public:

static const AFX_DATA CRuntimeClass classCMyClass;

virtual CRuntimeClass* GetRuntimeClass() const;

static CObject* PASCAL CreateObject();

2.IMPLEMENT_DYNCREATE展开:

CObject* PASCAL CMyClass::CreateObject()

{ return new CMyClass; }

CRuntimeClass* PASCAL CMyClass::_GetBaseClass()

{ return RUNTIME_CLASS(CBaseClass); }

AFX_COMDAT const AFX_DATADEF CRuntimeClass CMyClass::classCMyClass =

{"CMyClass", sizeof(class CMyClass),0xFFFF, NULL,&CMyClass::_GetBaseClass, NULL };

CRuntimeClass* CMyClass::GetRuntimeClass() const

{ return RUNTIME_CLASS(CMyClass); }

二.MFC中序列化宏组:

#define DECLARE_SERIAL(class_name)

#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema)

1.DECLARE_SERIAL展开:

protected:

static CRuntimeClass* PASCAL _GetBaseClass();

public:

static AFX_DATA CRuntimeClass classCMyClass;

virtual CRuntimeClass* GetRuntimeClass() const;

static CObject* PASCAL CreateObject();

AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, CMyClass* &pOb);

2.IMPLEMENT_SERIAL展开:

CObject* PASCAL CMyClass::CreateObject()

{ return new CMyClass; }

CRuntimeClass* PASCAL CMyClass::_GetBaseClass()

{ return RUNTIME_CLASS(CBaseClass); }

AFX_COMDAT AFX_DATADEF CRuntimeClass CMyClass::classCMyClass =

{"CMyClass", sizeof(class CMyClass), 1, CMyClass::CreateObject,&CMyClass::_GetBaseClass, NULL };

CRuntimeClass* CMyClass::GetRuntimeClass() const

{ return RUNTIME_CLASS(CMyClass); }

AFX_CLASSINIT _init_CMyClass(RUNTIME_CLASS(CMyClass));

CArchive& AFXAPI operator>>(CArchive& ar, CMyClass* &pOb)

{ pOb = (CMyClass*) ar.ReadObject(RUNTIME_CLASS(CMyClass));return ar; }

这两组宏中影响动态创建的两个关键的地方为:

1. DECLARE_DYNCREATE中将CRuntimeClass classCMyClass定义为static const类型;而在DECLARE_SERIAL中定义为static 类型,DECLARE_DYNCREATE中不需要修改CRuntimeClass中的m_pNextClass成员。

2.在IMPLEMENT_SERIAL中定义了AFX_CLASSINIT _init_CMyClass(RUNTIME_CLASS(CMyClass));这对构建类信息链表极为关键,如果没有这句,CRuntimeClass中的m_pNextClass的根本就毫无用处。

结论:

用DECLARE_DYNCREATE可以确定运行时的类的继承关系,但并没有建立类信息链表。

用IMPLEMENT_SERIAL可以建立运行时类信息链表,有了类信息链表就可以根据字符串在链表中查询出对应的类信息,然后创建对象。

例程下载地址:http://cmmy.vicp.net/bbs/viewFile.asp?Boardid=2&ID=2035

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有