MFC方式的动态创建

      大牛Linus对于C和C++的言论在CSDN引来了一波接着一波的“灌水”,愚以为语言这门“艺术”本身就是和具体环境密不可分的,脱离了一定的环境土壤和应用场景,语言自身都无产生的可能,更谈不上实际的应用价值,升华成一门艺术的境界。

      语言天生就是用来沟通的对象,不免产生碰撞,争论,分歧,演变抑或进化。古人云:有过则改,无则加勉。多发现外物的优点以弥补内心的缺失才是应当所思所学的。

     在我窥探到一个对象的创建过程,不,是对象创建前夕MFC所做的工作时(编织一张张天罗地网),被宏精妙的运用手法所震撼。这不是我们常常探讨设计模式的运用场景,MFC的宏可谓是把这点给发扬光大了,让我深刻的体验了一把。下面把自己的所思所学跟同学们分享下,写得不好,大家尽管拍砖:)

     创建一个对象A,自然是A *pA = new A;创建B,则B *pB = new B。现在需要动态创建A,B,怎么办?一个简单的办法是给每个class的做个标记(tag),代码内部判断是返回A或B,代码如下:

代码
 1 void *CreateObject(char *szTag)
 
2 {
 
3     if(0 == strcmp("A", szTag))
 
4     {
 
5         return new A;
 
6     }
 
7     else if(0 == strcmp("B", sztag))
 
8     {
 
9         return new B;
10     }
11     else
12     {
13         return NULL;
14     }
15 }

     上面的代码确实很是easy,给我一个tag就能返回你要对象。立马想到阿基米德的名言:给我一个支点,我就能撬动整个地球:)

     如果我们把class的tag和创建它的函数放到同一个struct中,定义如下:

class ObjectClass;
struct RuntimeClass
{
    TCHAR 
*szClassName;
    ObjectClass
* (*pCreateFn)();
};

    然后把这些RuntimeClass 以某种方式串联在一块,会是什么效果呢?呵呵,大概会是这个样子,传进一个tag,只要在这个”串串“(想起成都的麻辣烫阿)中搜一遍,就能返回对应的对象了:)。问题1:怎么串联呢?用stl的容器装起来?看看MFC的源码,原来在RuntimeClass中引入一个自身类型的指针变量,令其指向下一个RuntimeClass,显然,这样可以把n个RuntimeClass组成一个单向的链表,找的时候顺藤摸瓜就行了。窃以为,用stl的容器不是不行,但那样又单单依赖某一容器了。

    RuntimeClass的定义摇身变成:

struct RuntimeClass
{
    TCHAR *szClassName;
    RuntimeClass *pBaseClass;
    RuntimeClass *pNextClass;
    ObjectClass* (*pCreateFn)();

}

    又新增了pBaseClass指针,这样要找到当前ObjectClass的基类就方便了。OK,问题2:这些RuntimeClass在什么地方产生并连接起来呢?等代码运行到main里头?呵呵,再来看看MFC的源码,(打开VC6~敲入CObject,Alt+G)

    看到老祖宗脚下躺着一个static CRuntimeClass classCObject的成员变量,这意味classCObject在进入main之前应该有所初始化动作,这个初始化动作会是什么呢?如果在class A,B中都安放这样一个static CRuntimeClass的成员变量,上面所说的单向链表中的成员个体不就都有了末,事实上MFC确实也是这样做的。

    问题3:这些个static CRuntimeClass该如何连接起来呢?用MFC时我们可不用关心这些啊,呵呵。。。

    黎明前的时刻来了,念叨static。。。static,这里需要一个时机,或是一个触发动作,将各个CRuntimeClass连接在一起。能否开辟一个新的static变量,在其的构造函数中完成这个”统一大业“呢?这是否是异想天开?设计如下一个struct:

struct ClassList
{
    ClassList(RuntimeClass 
*pNewClass);
};

ClassList::ClassList(RuntimeClass
* pNewClass)
{
    pNewClass
->pNextClass=RuntimeClass::pFirstClass;
    RuntimeClass::pFirstClass
=pNewClass;
}

    这样每当一个ClassList产生时,自动将一个RuntimeClass连接到链表中。故事就讲到这吧,源码已上传,有兴趣的朋友可下载


 

 

 

posted @ 2009-12-18 00:00  kenco  阅读(275)  评论(0)    收藏  举报