饭中淹的避难所~~~~~

偶尔来避难的地方~

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  94 随笔 :: 0 文章 :: 257 评论 :: 0 Trackbacks
1- 我们来确定我们的目标
    我们需要事先一个叫做xCreator的模板类,能够根据一个基类TBase实例化出一个构造器类,能够通过Support<TObject>()的形式来支持TBase的派生类TObject,并能够通过 Create<TObject>() 的形式来构造出这个TObject的对象。

2- 思考我们事先这个目标的理论基础
    我们需要为每个TObject,创建一个单独的内部构造器,在Support调用的时候,创建并存储这个内部构造器。当Create调用的时候,我们寻找这个内部构造器,并且通过这个构造器构造出TObject的对象。

3- 内部构造器
    在设计内部构造器的时候,因为需要一个通用的返回TBase的接口,所以,我们把这个接口做成一个虚接口。
class xBaseCreator
{
public:
    virtual TBase 
* CreateObject() = 0;
}
;
    接下来,就是用模板来实现TObject的构造器了。
template <class TObject>
class xObjectCreator : public xBaseCreator
{
public:
    TBase 
* CreateObject() return new TObject();}
}
;
    有了内部的构造器,我们构造出外部的框架xCreator
template <class TBase> 
class xCreator
{
    
class xBaseCreator
    
{
    
public:
        virtual TBase 
* NewObject() = 0;
    }
;

    template 
<class TObject>
    
class xObjectCreator : public xBaseCreator
    
{
    
public:
        TBase 
* CreateObject() return new TObject();}
    }
;
public:
    template 
<class TObject> 
    
void Support()
    
{
    }


    template 
<class TObject>
    TBase 
* Create() 
    
{
    }

}
;
    现在,这个构造器已经有了雏形。

4- 实现Support
    Support说白了,就是通过TObject来创建一个内部构造器,并保存在xCreator<TBase>里面。
    那么我们需要在这个框架里加入一个容器来存储一系列的内部构造器。
xVector<xBaseCreator*> m_vInnerCreators;
    这里用的xVector是xlibplus的一部分,实际上它表现的跟STL的vector很相似,可以互换使用。
    下面就是Support的实际代码,很简单的一句(没有做一些安全性和重复的检测)
    template <class TObject> 
    
void Support()
    
{
        m_vInnerCreators.push_back( 
new xObjectCreator<TObject>() );
    }

5- 实现Create
    Create是整个构造器的重头戏。我们需要找到一种方法,能够通过TObject来找到它所对应的内部构造器。
    我们知道,同一个类中的静态成员的地址对于所有类成员来说,是一个相同的固定的地址。这样,这个地址,就可以标示一个特定的类。
    然后,我们知道,模板参数相同的模板类实例类,是同一个类。
    根据这两个,我们能够设计一种方法,通过静态成员的地址,来找到TObject对应的内部构造器的方法。下面就是这种方法的代码。

    首先,修改xBaseCreator的接口,提供一个获取类的Code的接口,这个Code就是模板类中的一个静态变量的地址。
   
    class xBaseCreator
    
{
    
public:
        virtual TBase 
* CreateObject() = 0;
        virtual 
void * GetClassCode() = 0;
    }
;
    然后,修改xObjectCreator,提供一个静态变量,以及GetClassCode()的实现。
    template <class TObject>
    
class xObjectCreator : public xBaseCreator
    
{
    
public:
        
static void * GetCode() {
            
static int nClassCode = 0;
            
return &nClassCode;
        }

        
void * GetClassCode() return GetCode();}
        TBase 
* CreateObject() return new TObject();}
    }
;

    最后,我们把Create写好。

    template <class TObject>
    TBase 
* Create() 
    
{
        
void * pClassCode = xObjectCreator<TObject>::GetCode();
        
forint i = 0;i < m_vInnerCreators.size();i ++ )
            
if( m_vInnerCreators[i]->GetClassCode() == pClassCode )
                
return m_vInnerCreators[i]->CreateObject();
        
return NULL;
    }
    从代码中可以看出整个方法都集中在这个Create里面的内部构造器搜索上面。这种方法有点类似RTTI。


到现在为止,这个通用构造器就基本完成了。代码比较糙,只是用来说明这个方法。至于删除之类的代码,就比较简单了.

下面是完整的这个构造器的代码,以及测试代码。

#include "stdafx.h"
#include 
<conio.h>


template 
<class TBase> 
class xCreator
{
    
class xBaseCreator
    
{
    
public:
        virtual TBase 
* CreateObject() = 0;
        virtual 
void * GetClassCode() = 0;
    }
;

    template 
<class TObject>
    
class xObjectCreator : public xBaseCreator
    
{
    
public:
        
static void * GetCode() {
            
static int nClassCode = 0;
            
return &nClassCode;
        }

        
void * GetClassCode() return GetCode();}
        TBase 
* CreateObject() return new TObject();}
    }
;
    xVector
<xBaseCreator*> m_vInnerCreators;
public:
    template 
<class TObject> 
    
void Support()
    
{
        m_vInnerCreators.push_back( 
new xObjectCreator<TObject>() );
    }


    template 
<class TObject>
    TBase 
* Create() 
    
{
        
void * pClassCode = xObjectCreator<TObject>::GetCode();
        
forint i = 0;i < m_vInnerCreators.size();i ++ )
            
if( m_vInnerCreators[i]->GetClassCode() == pClassCode )
                
return m_vInnerCreators[i]->CreateObject();
        
return NULL;
    }

}
;

class CBase
{
public:
    virtual 
int GetCode() const return 0;}
}
;

class CTest1 : public CBase
{
public:
    virtual 
int GetCode() const return 1;}
}
;

class CTest2 : public CBase
{
public:
    virtual 
int GetCode() const return 2;}
}
;

xCreator
<CBase> testcreator;
int _tmain(int argc, _TCHAR* argv[])
{
    testcreator.Support
<CTest1>();
    testcreator.Support
<CTest2>();
    CBase 
* p1 = testcreator.Create<CTest1>();
    CBase 
* p2 = testcreator.Create<CTest2>();
    printf( 
"code = %u / %u\n", p1->GetCode(), p2->GetCode() );
    getch();
    
return 0;
}






posted on 2008-04-01 02:22 饭中淹 阅读(1252) 评论(6)  编辑 收藏 引用

评论

# re: 搭建通用构造器 2008-04-01 09:05 梦在天涯
有新意!  回复  更多评论
  

# re: 搭建通用构造器 2008-04-01 09:48 raof01
不错。不过我认为xObjectCreator不需要继承xBaseCreator——已经通过模板来得到一定的多态性了。  回复  更多评论
  

# re: 搭建通用构造器 2008-04-01 09:53 饭中淹
@raof01
我为了实现无差别的遍历, 所以让他继承.
  回复  更多评论
  

# re: 搭建通用构造器 2008-04-01 10:06 mm
哎,直接用map不就得了,还用vector  回复  更多评论
  

# re: 搭建通用构造器 2008-04-01 10:14 饭中淹
@mm
用map和vector根这个方法无关。用vector比较好理解这个查找过程。
  回复  更多评论
  

# re: 搭建通用构造器 2008-04-03 12:46 w11
师傅,您好,哈哈,

想不到又碰见我吧  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理