??xml version="1.0" encoding="utf-8" standalone="yes"?>久久综合视频网站,午夜肉伦伦影院久久精品免费看国产一区二区三区,久久精品国产69国产精品亚洲http://www.shnenglu.com/agerlis/alexzh-cnWed, 07 May 2025 16:59:26 GMTWed, 07 May 2025 16:59:26 GMT60~写异常安全的代?loki::scopeguard)http://www.shnenglu.com/agerlis/archive/2007/02/11/18649.htmlagerlisagerlisSun, 11 Feb 2007 07:55:00 GMThttp://www.shnenglu.com/agerlis/archive/2007/02/11/18649.htmlhttp://www.shnenglu.com/agerlis/comments/18649.htmlhttp://www.shnenglu.com/agerlis/archive/2007/02/11/18649.html#Feedback3http://www.shnenglu.com/agerlis/comments/commentRss/18649.htmlhttp://www.shnenglu.com/agerlis/services/trackbacks/18649.html今天来讲讲怎么~写异常安全的代码?br />E序q行q程中,往往需要对一些流E加入异常处理,来提高程序的robust.比如
通过try catch来捕捉异?br />try
{
    pMemory = new char[MAX_BUF_SIZE];
}
catch(std::bad_alloc& e)
{
    //error handling,er:do something resource free
}
但在E序代码D中出现大量的try catch,不仅从美观,效率和程序输写上都是不怎么好?br />而另外一U对于异常的处理Ҏ是依赖于c++的ctor/dctor的匹配来做的Q就是所谓的
RAII,q个很容易让惛_std::auto_ptr
std::auto_ptr<int> tmp(new int);
通过new分配的对象会在tmp生命l束后,释放相关的资源,通过q种方式Q就能保证在E序异常Q或退出时Q已分配的对象能正确自动的释放拥有的资源Q而在对象声明周期内,可以保证资源的有效性?br />q种方式是今天blog要写的主要内容,我们可以看到std::auto_ptr作用范围很小Q只能对从堆上分配的对象q行理Q假如对文g打开句柄实行RAII,你也怼认ؓ再写个不是了,但这样只会造成源代码里充满了这些资源管理的c,q导致了一个严重的问题Q好的结构在J琐的流畅前面变的难堪?br />那怎么样对q个q行泛化Q从而能Ҏ如从单的指针释放Q文件句柄维护,甚至相关的成员函数。我们来看下loki::socpeguard是怎么实现的:
先看下基本的用法
(1)  FILE* hFileOpen = fopen(....);
(2)  LOKI_ON_BLOCK_EXIT(flose,hFileOpen);
line2会在出LOKI_ON_BLOCK_EXIT域或E序异常l束时被调用Q下面是对类成员的调?br />void CTestObject::Create
{
    LOKI_ON_BLOCK_EXIT_OBJ(*this,FressResouce);
    ...
}
同上面差不多Q会在这个函数结束后或异常结束后调用cL员的FreeResource.在正常流E结束后Q可以通过调用Dismiss来防止对FreeResouce的调用,即类似数据库操作的commit操作。下面来分析下LOKI的实玎ͼ
从上面可以看刎ͼRAII的是Q?br />1Q构造函数对资源的获?br />2Q稀构函数对资源的释?br />先来看下LoKi对上面那2个宏的定?br />#define LOKI_ON_BLOCK_EXIT      Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = Loki::MakeGuard

#define LOKI_ON_BLOCK_EXIT_OBJ  Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = Loki::MakeObjGuard
上面的Loki::ScopeGuard是一个基cȝ别名
typedef const ScopeGuardImplBase& ScopeGuard;
而LOKI_ANONYMOUS_VARIABLE(scopeGuard)用来我们产生唯一的名字,有时假如需要调用Dismiss的话Q则需要自己去实现宏定义的内容Q这h能通过对象讉K。Loki::MakeGuard或Loki::MakeObjGuard是用来生对象的实际cd的,下面是一?br />Loki::MakeGuard的例子:
template <typename F, typename P1>
inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
{
    return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
}
可以看到ScopeGuardImpl1<F, P1>是要产生的具体类型,MakeGuard通过函数参数的数目来重蝲的,而MakeGuard此处的作用是要睡M...-_-'',作用是利用函数自动推导出参数的类型,q样免M指定ScopeGuardImpl1的类型的ȝQ?br />ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
单的q回对象的一个时变量,qassignl一个上面的一个scopeguard的实例,q里依赖一个C++的特性,临时变量的声命周期和通过他初始化的引用类型的声明周期是一致的?/p>

从上面可以看到Loki定义了一个ScopeGuardImplBase的基cR这个类定义了一个基本的ҎDismiss,以及相关的状态。下面是loki中这个类的定?br />class ScopeGuardImplBase
{
    ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
 protected:
    ~ScopeGuardImplBase()
    {}
    ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
        : dismissed_(other.dismissed_)
    {
        other.Dismiss();
    }
    template <typename J>
    static void SafeExecute(J& j) throw()
    {
        if (!j.dismissed_)
           try
           {
              j.Execute();
           }
           catch(...)
           {}
     }
       
     mutable bool dismissed_;
public:
     ScopeGuardImplBase() throw() : dismissed_(false)
     {}
     void Dismiss() const throw()
     {
         dismissed_ = true;
      }
};
可以看到c里面定义了上面所说的一些属性,其中SafeExecute用来提供子类同一的资源释放方法,q调用子cȝҎ来具体操作,因ؓ相关的函敎ͼ变量都保存在具体的子c,可以看到q个函数使用了try catchQ这里加q个的目的是Q因源释放要在子cȝE构里被触发,而调用具体的Ҏ是外面传q来的,所以无法保证一定是异常安全的,而假如在E构里面异常的话,会导致程序的行ؓ无法定义?br />下面具体来看下一个子cȝ实现Q?br />template <typename F, typename P1>
class ScopeGuardImpl1 : public ScopeGuardImplBase
{
public:
    static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
    {
        return ScopeGuardImpl1<F, P1>(fun, p1);
    }
    ~ScopeGuardImpl1() throw()
    {
        SafeExecute(*this);
    }
    void Execute()
    {
        fun_(p1_);
    }
protected:
    ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
    {}
    F fun_;
    const P1 p1_;
};
在LoKi里面可以看到很多cMScopeGuardImpl1的定义,比如ScopeGuardImpl0Q?br />ScopeGuardImpl2Q可以发现最后面的数字表C具体参数的数目?br />可以看到上面所说的MakeGuard的定义,以及对基cL法的调用Q可以看到构造函数接收的cdQ一个函数对象,和一些参数对象,q保存,对于成员函数的scopeguard,LoKi定义?些相似的c,主要是增加了对象的引用,q有是函数的调用方式上?br />上面可以看到参数是通过值的方式来保存的而不是通过引用。而且是const属性的Q下面是相关的分析?br />1Q通过传值的方式Q从而避免了异常抛出Ӟ可能引用的对象被E?br />2Q加const属性,从而保证了在func需要参数是reference时而保存的参数是非const时生相应的~译错误Q因为对reference传hconst non-reference形式是错误的?br />而对?的方式,存在的一U问题是假如操作的fun需要传入引用,那传q去的值就无法在释攄函数中被改变Q?是对q种的一U类似契U似的编E,Loki 提供的方法是通过一个中间对象来保存操作参数的引用,q赋予这个对象自动{换功能。下面是q个cȝ定义Q?br />template <class T>
class RefToValue
{  
public:
    RefToValue(T& ref) : ref_(ref)
    {}
    RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
    {}
    operator T& () const
    {
        return ref_;
    }
private:
    // Disable - not implemented
    RefToValue();
    RefToValue& operator=(const RefToValue&);
       
    T& ref_;
};
可以很清楚的看到cȝ实现Q下面是一个工L
template <class T>
inline RefToValue<T> ByRef(T& t)
{
     return RefToValue<T>(t);
}
下面l个具体的例子,假如
template<typename _Ty>
void SAFEDELETE(_Ty*& ptr)
{
   if (NULL != ptr)
      delete ptr;
   ptr = NULL;
}

char* ptr = new char;
 
{
    LOKI_ON_BLOCK_EXIT(SAFEDELETE<char>,Loki::ByRef(ptr));
}
 
if (NULL == ptr)
  std::cout << "NULL" << std::endl;
基本上就q么多了QsleepM
                                                    alex_yuu



agerlis 2007-02-11 15:55 发表评论
]]>
解析boost::anyhttp://www.shnenglu.com/agerlis/archive/2007/02/11/18648.htmlagerlisagerlisSun, 11 Feb 2007 07:54:00 GMThttp://www.shnenglu.com/agerlis/archive/2007/02/11/18648.htmlhttp://www.shnenglu.com/agerlis/comments/18648.htmlhttp://www.shnenglu.com/agerlis/archive/2007/02/11/18648.html#Feedback0http://www.shnenglu.com/agerlis/comments/commentRss/18648.htmlhttp://www.shnenglu.com/agerlis/services/trackbacks/18648.html前几天一个朋友给我看?D代码:
any temp; //any is a class
temp = 1;
temp = "a";
temp = x; //x is a abstract class

看到q段代码着实下??初期的感觉象void*指针那样Q又象variant变量。但感觉q是比较新颖的,-_-''也许我是菜鸟的原因,在脑袋{了一下后Q我实现了自q一个类Q用来接受Q何参敎ͼ起初我认为any应该是个typedef,而接收的cd也是前面知道?-_-''又没弄清需求就dC)Q所以实C个接收Q何参数的c需要个typelist,和对每种cd的泛化,下面是class的定义:

template<typename _typelist>
class any
{
public:
 typedef typename Loki::TL::TypeAtNonStrict<_typelist,0>::Result param1;
 typedef typename Loki::TL::TypeAtNonStrict<_typelist,1>::Result param2;
 typedef typename Loki::TL::TypeAtNonStrict<_typelist,2>::Result param3;
 typedef typename Loki::TL::TypeAtNonStrict<_typelist,3>::Result param4;
 typedef typename Loki::TL::TypeAtNonStrict<_typelist,4>::Result param5;

 any(param1 param):
  m_param1(param){}

 any(param2 param):
  m_param2(param){}

 any(param3 param):
  m_param3(param){}

 any(param4 param):
  m_param4(param){}

 template<typename _Ty>
 const _Ty&  Get()
 {
     class CERROR_ACCESS_DENIED;
     LOKI_STATIC_CHECK((Loki::TL::IndexOf<_typelist,_Ty>::value != -     1),CERROR_ACCESS_DENIED);

     return __Access<_Ty>();
 }
private:
 template<typename _Ty>
 _Ty&  __Access();

 template<>
 param1& __Access<param1>() {return m_param1;}

 template<>
 param2& __Access<param2>() {return m_param2;}

 template<>
 param3& __Access<param3>() {return m_param3;}

 template<>
 param4& __Access<param4>() {return m_param4;}

 param1  m_param1;
 param2  m_param2;
 param3  m_param3;
 param4  m_param4;
};

typedef any<Loki::TYPE_LIST_3(int,float,char)> ANY;

q样g可以接收Q何类型了,也可以取出数据,取出时必要知道相应的类型,而且Q假如类型不在列表里面,则编译期出错
class CERROR_ACCESS_DENIED;
LOKI_STATIC_CHECK((Loki::TL::IndexOf<_typelist,_Ty>::value != -     1),CERROR_ACCESS_DENIED);
q样Q?_-''g可以了Q只要所接收的类型可以拷贝即可。但有个明了的缺P?是接收的类型必ȝ译期写死Q假如不写死的话Q我个h开始的认ؓ是加一个基c,-_-''
q是?q我那位朋友,让我了解到boost::any的用?/div>
下面是boost::any的具体分?我们要达C面几个要求:
1Q可以接收Q何类型的数据Q具有value属?
2: 可以方便的取出数?/div>
3Q型别安全,不象void*
下面是boost::any的实玎ͼ我按部分_而且省去我认Z重要的东西,因ؓ太长了,q会影响我blog的收视率?/div>
1Q首先来看下他的构造和E?-_-''错别字)
 any()
    : content(0)
{
}
 
 template<typename ValueType>
 any(const ValueType & value)
    : content(new holder<ValueType>(value))
{
}
 
any(const any & other)
    : content(other.content ? other.content->clone() : 0)
 {
 }
 
 ~any()
 {
     delete content;
 }
从构造函数可以看刎ͼany可以接受默认的,M其他值包括ant本nQ在E构里面可以看到对content的释放,content在这里是一个基cȝ指针Q是any内部实现的,我们可以看到Q在对any构造是有种ҎQ?/font>
Q?Qcontent(new holder<ValueType>(value))
Q?Qcontent(other.content ? other.content->clone() : 0)
E后会看到holder是派生自contentcd的一个模板实玎ͼ也许讲到q里Q有些应该明白了any是怎么保存Mcd的吧Q对于其他any的构造,我们发现调用了content的一个cloneҎQ很明显q是content的一个虚ҎQ这个方法的存在得以让我们运用虚函数的机制正的拯对象Q下面会看到q只是个单的new操作?/font>
2:来看下any的operator =的重?/div>
any & swap(any & rhs)
{
     std::swap(content, rhs.content);
     return *this;
}
 
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
    any(rhs).swap(*this);
    return *this;
}
 
any & operator=(const any & rhs)
{
      any(rhs).swap(*this);
      return *this;
}
可以看到operator =Q接收Q何其他类型的参数QswapҎ的实玎ͼ用来交换2个对象的content指针Q我们可以看到operator =里面临时对象的构建,在函数结束后Q自动释攑֎来content的对象,q有点RAII味道。(http://blog.sina.com.cn/u/1019039487)独家菜。?/font>
3Q下面来看下辅助c?/div>
 bool empty() const
 {
      return !content;
 }
 
 const std::type_info & type() const
 {
      return content ? content->type() : typeid(void);
 }
可以看到。一个empty,一个type,很Ş象?/div>
4Q下面来看下上面content所指的对象Q以及any怎么保存McdQ以及这U怎么保证型别安全
class placeholder
{
public: // structors
     virtual ~placeholder()
     {
     }
public: // queries
      virtual const std::type_info & type() const = 0;
      virtual placeholder * clone() const = 0;
};
 
template<typename ValueType>
class holder : public placeholder
{
public: // structors
     holder(const ValueType & value)
              : held(value)
     {
     }
public: // queries
     virtual const std::type_info & type() const
     {
         return typeid(ValueType);
     }
 
     virtual placeholder * clone() const
     {
          return new holder(held);
     }
public: // representation
     ValueType held;
};(-_-''格式矫正真是cd)
 
placeholder是上面content指向的对象,可以看到他定义的一些提供给any调用的函数和虚基本必ȝ虚稀构函敎ͼ可以看到any对content调用了delete)
下面?font color="#0000ff">holder的实玎ͼholder是一个模板,里面定义?/font>
ValueType held;
很明星是any用来保存Mcd的,回顾下上面所说的any初始化content?U方?/font>
Q?Qcontent(new holder<ValueType>(value))
Q?Qcontent(other.content ? other.content->clone() : 0)
从这个地方可以看到怎么初始化holder对象Qƈ保存到content.注意到这里的held是public的,q样提供了Ҏ据访问的功能Q在讉K的时候必要知道具体要访问的cdQ才能调用相应的static_cast或者dynamic_cast来操作,而这样其实也提供了型别安全的保证Qeg:不象malloc,q回void*,然后()转换一下?/font>
5Q看下怎么讉Kany里面的属性|q里׃列D出所有的实现Q因为有些是对const的版本?/div>
template<typename ValueType>
ValueType * any_cast(any * operand)
{
    return operand && operand->type() == typeid(ValueType)
                    ? &static_cast<any::holder<ValueType> *>  (operand->content)->held
                    : 0;
}
 
template<typename ValueType>
ValueType any_cast(const any & operand)
{
     typedef BOOST_DEDUCED_TYPENAME        remove_reference<ValueType>::type nonref;
 
   const nonref * result = any_cast<nonref>(&operand);
   if(!result)
            boost::throw_exception(bad_any_cast());
    return *result;
}//q里L1些原来实现的代码和注?/font>
可以看到具体的实现方式&dynamic_cast的逻辑差不多,对引用的cast有可能抛出异常。通过上面q种方式Q就辑ֈ了对数据的读取,d时必ȝ道里面的数据cd。可以看出any只能保存一个|-_-''不向我那个,可以同时保存不同cd的倹{?/font>
6Qextension
可以通过std::vector<boost::any> anys,来构Z个Q何类型的列表Q但讉K比较ȝ?/div>
也可以通过any来达到虚函数不能为template的限Ӟ因ؓ一个是静态的一个是动态的Q?/div>
象下面:
class CBase
{
 public:
     virtual void Set(boost::any) = 0;
};
 
class CHild:
     public CBase
{
 public:
     virtual void Set(boost::any param)
     {
          m_value = param;
     }
 private:
     boost::any  m_value;
};
 
CHild test;
CBase* ptr = &test;
ptr->Set(1);
ptr->Set('a');
7.finish...ȝ完成?..-_-''要变唐僧?..
                                                  alex. agerlis@163.com


agerlis 2007-02-11 15:54 发表评论
]]>旉理http://www.shnenglu.com/agerlis/archive/2007/02/11/18647.htmlagerlisagerlisSun, 11 Feb 2007 07:54:00 GMThttp://www.shnenglu.com/agerlis/archive/2007/02/11/18647.htmlhttp://www.shnenglu.com/agerlis/comments/18647.htmlhttp://www.shnenglu.com/agerlis/archive/2007/02/11/18647.html#Feedback0http://www.shnenglu.com/agerlis/comments/commentRss/18647.htmlhttp://www.shnenglu.com/agerlis/services/trackbacks/18647.html 听说q一U时间管理的Ҏ,是用来怎么安排d和时间的,下面是大概的概念?
 

                               time - task

图中头指向的方向表C紧q度的添?那么下面是关?,2,3,4的定?

一:d比较重要,但相应的旉也很?/p>

?d是长期Q?但比较重?/p>

?不那么重要的d,旉也很?/p>

?不需要多长时间的非重要Q?/p>

现在分析下上面的q些:
对于一:往往q个时候处于时间的dead line状?而此时往往是我们都不想要的,熟话说事情是急不来的,q个时候往往会导致质量的下降.

对于?我们有充的旉来做重要的Q?q正是我们想要的,?怎么做才能其不会过渡到区间一?转ؓ区间1往往会由于h的惰性生的,关键是要提前做事.安排好时?

对于?往往是一些可以辅助我们成长的事情,q些东西Ҏ们有益处,q对全面的发展vC很好的作?-_-''p我学吉他..

对于?是些旉?但不重要的Q?比如要帮助h去google一些资?

从上面可以看?区间一实际上是最差的,但ؓ了做好区?,我们必须要尽量减区?的䆾?而对于全面的发展,我们也要安排旉到区?.q也是很重要?



agerlis 2007-02-11 15:54 发表评论
]]>d命o行参?/title><link>http://www.shnenglu.com/agerlis/archive/2007/02/11/18646.html</link><dc:creator>agerlis</dc:creator><author>agerlis</author><pubDate>Sun, 11 Feb 2007 07:53:00 GMT</pubDate><guid>http://www.shnenglu.com/agerlis/archive/2007/02/11/18646.html</guid><wfw:comment>http://www.shnenglu.com/agerlis/comments/18646.html</wfw:comment><comments>http://www.shnenglu.com/agerlis/archive/2007/02/11/18646.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/agerlis/comments/commentRss/18646.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/agerlis/services/trackbacks/18646.html</trackback:ping><description><![CDATA[ <div>以前Cd命o行参数感觉太ȝ,而且不容易记?下面是另外一U命令行的读取方?/div> <div>通过GetCommandLine(),来返回当前的命o?</div> <div> <font color="#0000ff">setlocale(LC_ALL, ".ACP");<br />std::wcout << GetCommandLine() << std::endl;</font> </div> <div> <font color="#000000">下面是输?</font> </div> <div> <font color="#0000ff">"e:\学习E序\consol3\debug\consol3.exe" a b c</font> </div> <div> <font color="#000000">对于命o行的参数d用CommandLineToArgvW,可以把命令行参数转换成字W串数组的Ş?/font> </div> <div> <font color="#0000ff">int nums = 0;<br />TCHAR** temp = CommandLineToArgvW(GetCommandLine(),&nums);</font> </div> <div> <font color="#0000ff">for(int i = 0; i < nums; i++)<br />{<br />  std::wcout<< temp[i] << std::endl;<br />}</font> </div> <div> <font color="#000000">下面是输?</font> <br /> <font color="#0000ff">e:\学习E序\consol3\debug\consol3.exe<br />a<br />b<br />c</font> <br />可以看到命o行参C下标=1的元素开?</div> <div>感觉q种形式比较好记?/div> <img src ="http://www.shnenglu.com/agerlis/aggbug/18646.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/agerlis/" target="_blank">agerlis</a> 2007-02-11 15:53 <a href="http://www.shnenglu.com/agerlis/archive/2007/02/11/18646.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习abstract factoryW记http://www.shnenglu.com/agerlis/archive/2007/02/11/18645.htmlagerlisagerlisSun, 11 Feb 2007 07:53:00 GMThttp://www.shnenglu.com/agerlis/archive/2007/02/11/18645.htmlhttp://www.shnenglu.com/agerlis/comments/18645.htmlhttp://www.shnenglu.com/agerlis/archive/2007/02/11/18645.html#Feedback0http://www.shnenglu.com/agerlis/comments/commentRss/18645.htmlhttp://www.shnenglu.com/agerlis/services/trackbacks/18645.htmlabstract factory.感觉是个很玄的名字,即在我写学习笔记的时候,我也因ؓ~少现实中的实践而对其了解不深。^^希望.... 多指?br />Name:
   abstract factory
Addressed Problem:
   提供对同1U相兛_象的创徏。比如在E序里面Q希望根据用户配|来讄UIҎQ比如方??Q对应的UI也存?套不同的实现c,比如对于ScrollBar,有CScrollBar1和CScrollBar2Q都l承自ScrollBar。也许在E序里面有很多这LcR这样你在应用UI实例化类时就必须要选择比如
IScrollBar* pScrollBar = NULL;
if (_use_ui_1)
   pScrollBar = new CScrollBar1;
else
   pScrollBar = new CScrollBar2;
也许你这h觉没多大关系Q但惌下,在程序的多处都存在这L选择Qؓ什么我不选择一Uless error phone的方法呢Q比?br />pScrollBar = Create(...);
q样一U简单的方式呢?而且上面的写法也引进?个避短,也就是在产生pScrollBarӞ涉及C具体的实现类Q这在面向对象这Uprogram to interfaceq样的语a中是很忌讳的事情。比如,在加UUIҎQ也怽会再写个else,q样{于自己把自己往火堆里面推。你是一个勤奋的E序员,但不是个优秀的程序员^^.也许有h会说Q我可以利用prototypeq样的方式来啊。这P在程序的外面配置一下每个类的prototype可以了Q或怹可以用object factory啊,都可以(^^g是哦Q我也没学过q?个的_解决上面的问题,一个通过DoClonecM的,1个通过ID或其他的Q其实在应用上面?U时Q自然的导出了abstract factory.Z么呢Q因Z面的2U,你都需要设|多个的原型或ID。比如也许在CUIManager的构造里面写贼大的if
if (_use_ui_1)
{
    ...//讄UI_1下所有的prototype
}
else
{
    ...//讄UI_2下所有的prototype
}
也许在将来的莫天Q在加上UI_3,则。再写个if.也许大家可能会想Q我在应用uiӞ我就知道了所要创建的对象Qؓ什么我不把上面宝装一下改成:
if (_use_ui_1)
 //讄factory_1
else
 //讄factory_2
然后在抽象出来的IFactory里面提供创徏q些UI Class的方法,比如QCreateScrollBase.{等Q这样就有了abstract factory 的雏形?br />基础实现
/*
 试abstract factory模式
*/

class IScrollWindow
{
public:
 virtual void DrawScroll(void) = 0;
};

class IListWindow
{
public:
 virtual void DrawList(void) = 0;
};

class ICreateWindowFactory
{
public:
 virtual IScrollWindow* CreateScrollWindow(void) = 0;

 virtual IListWindow* CreateListWindow(void) = 0;
};

class CBlueWindowFactory:
 public ICreateWindowFactory
{
 class CBlueScrollWindow:
  public IScrollWindow
 {
 public:
  virtual void DrawScroll(void)
  {
   std::cout << "draw blue scroll" << std::endl;
  }
 };

 class CBlueListWindow:
  public IListWindow
 {
 public:
  virtual void DrawList(void)
  {
   std::cout << "draw blue list" << std::endl;
  }
 };
public:
 virtual IScrollWindow* CreateScrollWindow(void)
 {
  return new CBlueScrollWindow;
 }

 virtual IListWindow* CreateListWindow(void)
 {
  return new CBlueListWindow;
 }
};

class CRedWindowFactory:
 public ICreateWindowFactory
{
 class CRedScrollWindow:
  public IScrollWindow
 {
 public:
  virtual void DrawScroll(void)
  {
   std::cout << "draw red scroll" << std::endl;
  }
 };

 class CRedListWindow:
  public IListWindow
 {
 public:
  virtual void DrawList(void)
  {
   std::cout << "draw red list" << std::endl;
  }
 };
public:
 virtual IScrollWindow* CreateScrollWindow(void)
 {
  return new CRedScrollWindow;
 }

 virtual IListWindow* CreateListWindow(void)
 {
  return new CRedListWindow;
 }
};
在需要用的地方,可以这P
ICreateWindowFactory* pCreateWindow1 = new CBlueWindowFactory;

 pCreateWindow1->CreateListWindow()->DrawList();
 pCreateWindow1->CreateScrollWindow()->DrawScroll();
假如需要用不同的工厂,则更换不会媄响到调用处的代码。因为掉用工厂的地方是面向接口的。其实abstract factory的理念应该是比较单的(^^瞎猜?.基本讲完了什么是抽象cd厂,他要解决的一些问题以及怎么解决?个小而ؕ的demo代码Dc下面来看下我们怎么泛化q个cd厂,q个会涉及到loki里面的具体实玎ͼ大家要加满a啊,因ؓ泛化cd厂是一件不Ҏ的事情啊?/p>

泛化_1
首先Q?^^q部分我也不是很?要泛化的是abstract factory的接口,p上面的CreateScrollWindow和CreateListWindowQ在泛化旉要的信息是要创徏的同1l对象的相关接口比如IScrollBar,IList{等Q在loki里面Q要?个类泛化1l接口,可以通过GenScatterHierarchy来将unit应用到typelist里的?个类型,q将该类从unit<type>zQ从而得?l接口。GenScatterHierarchy做了什么呢Q他产生了啥呢?具体的可以看morden c++里面的实现。通过GenScatterHierarchy我们得到了我们要?l接口。下面是loki里面对这个得相关实现
template <class T>
class AbstractFactoryUnit
{
public:
    virtual T* DoCreate(Type2Type<T>) = 0;
    virtual ~AbstractFactoryUnit() {}
};

可以看到Q上面定义了2个函敎ͼ而这个类是我上面说得调用GenScatterHierarchyӞL化时对typelist得每个类型应用得templatec,而最后生得也将是类?font color="#0000ff">AbstractFactoryUnit<IScrollBar>的类Q?/font>我们具体的抽象工厂从q些z。至于pure dctorq个大家应该都知道啥作用。下面来看Abstract Factory 的泛化:

template
<
    class TList,
    template <class> class Unit = AbstractFactoryUnit
>
class AbstractFactory : public GenScatterHierarchy<TList, Unit>
{
public:
     typedef TList ProductList;
       
     template <class T> T* Create()
     {
        Unit<T>& unit = *this;
        return unit.DoCreate(Type2Type<T>());
     }
 };
可以看到q个即由GenScatterHierarchy来得C我们惌的东ѝ提供了Create的模板函敎ͼ使得我们可以象这样factory.Create<IScrollBar>()的方便Ş势来调用。ProductList是对于抽象工厂要创徏的类型的重命名。方便后面在产生实际的类型时Q获取对应的cd信息Q对于DoCreate的参敎ͼ大家应该都明白这是重载用的,那用在哪里呢Q下面会介绍?/font>

泛化_2
在辛苦介l完泛化抽象工厂的接口后Q我们可以通过cM的方式来定义1个abstract factory的接?br />Loki::AbstractFactory<LOKI_TYPELIST_2(IScrollBar,IListWindow)>
下面我们来介l最后的Q我们怎么来提供抽象工厂的实现Q首先是对象的创建,loki里面提供了默认的创徏的方法,当然我们可以修改或用特化的版本来做选择?br />template <class ConcreteProduct, class Base>
class OpNewFactoryUnit : public Base
{
     typedef typename Base::ProductList BaseProductList;
   
protected:
     typedef typename BaseProductList::Tail ProductList;
   
public:
     typedef typename BaseProductList::Head AbstractProduct;
     ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
     {
          return new ConcreteProduct;
     }
};
可以看到DoCreate是我们的核心部分Q里面调用了new来创建对象。而这里也让我们看到这应该是上面创建对象的重蝲。而Type2Type的作用正是在q里体现作用Q因为c++无法通过函数q回值来重蝲不同的对象。也怽会看C面的一些类型定义,包括OpNewFactoryUnit?个模板参敎ͼW?个模板参数是实现GenLinearHierarchy必备的GenLinearHierarchy和上面的GenScatterHierarchy的核心思想一P都是通过L化来实现的,不过GenLinearHierarchy产生的是U性的l承体系Q中间夹杂着比如OpNewFactoryUnit<IScrollBar,GenLinearHierarchy<...> >q样的Şѝ下面来看下抽象工程的具体实现的泛化Q联pv来就能对上面的理解了
template
<
    class AbstractFact,
    template <class, class> class Creator = OpNewFactoryUnit,
    class TList = typename AbstractFact::ProductList
>
class ConcreteFactory
     : public GenLinearHierarchy<
     typename TL::Reverse<TList>::Result, Creator, AbstractFact>
{
public:
    typedef typename AbstractFact::ProductList ProductList;
    typedef TList ConcreteProductList;
};
可以看到ConcreteFactory由GenLinearHierarchy来驱动生我们想要的Q本来这个脓图比较明朗点Q但我懒的画Q哈哈。从GenLinearHierarchy的参数来看,W?个是具体的实现类的typelist,比如LOKI_TYPELIST2(CScrollBar_1,CListWindow_1),至于Z么要对类型做reverse操作Q因为在cȝ基础体系产生后,typelist的第1个元素,在承体pL׃往上的Q而于上面由OpNewFactoryUnit{定义的ProductList的Head定义的自上往下的是相反的Q所以这里应用了reverse操作。Creator是上面的OpNewFactoryUnit或你自定义的元素。ƈ在具现化是,应用typelist的每个类型。AbstractFact是承体现的最端Q这个应该很明显Q就是上面定义的AbstractFactory,q样啥都明确了,具体的接口,Ҏ口的函数的重载都已经泛化完成。下面是Q^^睡死了,睡觉MQ简单从便,上面均未调试?.至于Z么会把第3个参数默认ؓ抽象cd厂接口的ProductListQ这个和loki用基于prototype的Creator有关pR?^^俺是菜鸟Q就只能到这里了)
对abstract factory的看法,优点在上面的已经说过了,定在,我们要添?U对象的创徏Ӟ都要MҎ口的定义Q当然后面的泛化也ؓ我们解决了些问题Q但泛化对于参数的传递不怎么好用Q可以通过提供新的OpNewFactoryUnit来适当解决?br />                                                    agerlis.2007.2.10 0:22


agerlis 2007-02-11 15:53 发表评论
]]>
关于handle-body的用法及loki::PimplT的分?/title><link>http://www.shnenglu.com/agerlis/archive/2007/02/11/18644.html</link><dc:creator>agerlis</dc:creator><author>agerlis</author><pubDate>Sun, 11 Feb 2007 07:52:00 GMT</pubDate><guid>http://www.shnenglu.com/agerlis/archive/2007/02/11/18644.html</guid><wfw:comment>http://www.shnenglu.com/agerlis/comments/18644.html</wfw:comment><comments>http://www.shnenglu.com/agerlis/archive/2007/02/11/18644.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/agerlis/comments/commentRss/18644.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/agerlis/services/trackbacks/18644.html</trackback:ping><description><![CDATA[ <p> <font color="#660000">handle-body</font>,睡死了,但还是得坚持下。其实这个是很简单的概念<br />q个也称gؓ<font color="#660000">pimpl</font>,是private implemention的羃写,下面涉及到的都叫做pimpl, 那用q个到底有什么好处呢Q?br />1Q可以把具体的实Cclient端封装,q样即修改实现Q只要不修改头文Ӟ对client端来_是没有Q何媄响的Q甚至不改变代码?q制Ҏ?br />2Q加速编译时_我们知道有时头文件有太多的实玎ͼ会导致包含这个头文g的其他文件的~译旉增加Q通过pimpl,我们把实C头文件移到cpp里面Q从而减了其他包含q个文g的编译时_加快~译速度<br />3Q减依赖,q个实际上也增加了编译的速度Q可以不对client端暴露一些实C的头文gQ从而减了依赖说了q么多,下面来看下一个简单的pimpl的实现。是用loki的类来实现的。哈哈,睡死了,h<br /><font color="#0000ff">/*.h*/<br />class CTest<br />{<br />public:<br />    void Test();<br />private: <br />    Loki::PimplT::Type m_impl;<br />};<br />------------------------------------------------------------------- /*.cpp*/<br />template<><br />struct Loki::ImplT<br />{<br />public:<br />    void Test() { std::cout << "test" << std::endl; }<br />};<br /><br />void CTest::Test() { return m_impl->Test(); }</font><br />上面只是个很单很单的例子,以至于有些还无法体会到pimpl的作用,但相信在实践中你会体会到Q把原来定义在CTest里面的一些私有的ҎQ成员,全部挪到ImplT里面Ӟ你会体会刎ͼq个CTest的头文g里include了很的_他可以说完成了原始的使命Q达C功能性接口的作用Q而其他原来定义在头里?h,可以全部挪到cpp里了。下面来分析下loki是怎么实现的。可以看到实现pimpl首先需要牵|声明pre definec,loki通过模板的全特化来实Cq个的隐藏,从而避免了把具体的实现cL露给client的弊端。下面来看下q个泛化的pre define: template struct ImplT; 哈哈Q很单,再看上面我的cpp里的定义Q大家结合上面也许就明白了吧Q部q,q里需要注意的是,CTest的构造函数要写后面,不然can;t compile. 但是Qؓ什么具体的实现cLImplT但,前面?br /><font color="#0000ff">Loki::PimplT::Type m_impl</font>;<br />那Loki::PimplT::Type是什么用的,我们知道Q假如保存原始的<br /><font color="#0000ff">Loki::ImplT<CTest>* m_impl;</font><br />然后new一?其实q样只存?个问题,2个不方便Q?br />1Q问题是q样的原始指针,不能传播const信息Q也是_对象CTest转ؓconst的化Q他里面的指针类型不是同样随着带有const属性,也就是说Q假如此时指针指向的对象有个函数Q提供了constQnone const的,此时Q还是会调用non const的,所以,外界q是可以通过q个对象来做修改?br />2Q?个不方便是,你必d对象实现new和delete.<br />下面来看下loki是怎么做的<br /><font color="#0000ff">template<class T><br />struct ConstPropPtr<br />{<br />        explicit ConstPropPtr(T* p) : ptr_(p) {}<br />        ~ConstPropPtr() { delete  ptr_; ptr_ = 0; }<br />        T* operator->()    { return  ptr_; }<br />        T& operator*()    { return *ptr_; }<br />        const T* operator->() const    { return  ptr_; }<br />        const T& operator*()  const    { return *ptr_; }<br />   <br />private:<br />        ConstPropPtr();<br />        ConstPropPtr(const ConstPropPtr&);<br />        ConstPropPtr& operator=(const ConstPropPtr&);<br />        T* ptr_;<br />};</font></p> <p> <font color="#000000">q个cL供了寚w?的解冟뀂下面会讲解Q主要的ҎQ对象不同于指针Q对象能传递const属性?br />下面看下pimlT的定义:<br /></font> <font color="#0000ff">template<class T, template<class> class Ptr = ConstPropPtr><br />struct PimplT<br />{<br />        typedef T Impl;</font> </p> <p> <font color="#0000ff">        // declare pimpl<br />        typedef Pimpl<ImplT<T>, Ptr<ImplT<T> > > Type;</font> </p> <p> <font color="#0000ff">        // inherit pimpl<br />        typedef PimplOwner<ImplT<T>, Ptr<ImplT<T> > > Owner;<br />};<br /><font color="#000000">可以看到?/font>Type</font> <font color="#000000">的定义,下面的owner也不说了Q直接到Pimpl,</font> </p> <p> <font color="#0000ff">template<br /><   <br />        class T,<br />        typename Pointer = ConstPropPtr<T><br />><br />class Pimpl<br />{<br />public:</font> </p> <p> <font color="#0000ff">        typedef T Impl;</font> </p> <p> <font color="#0000ff">        Pimpl() : ptr_(new T)<br />        {}</font> </p> <p> <font color="#0000ff">        ~Pimpl()<br />        {<br />            typedef char T_must_be_defined[sizeof(T) ? 1 : -1 ];<br />        }</font> </p> <p> <br /> <font color="#0000ff">        T* operator->()<br />        {<br />            return ptr_.operator->();<br />        }</font> </p> <p> <font color="#0000ff">        T& operator*()<br />        {<br />            return ptr_.operator*();<br />        }</font> </p> <p> <font color="#0000ff">        const T* operator->() const<br />        {<br />            return ptr_.operator->();<br />        }</font> </p> <p> <font color="#0000ff">        const T& operator*() const<br />        {<br />            return ptr_.operator*();<br />        }</font> </p> <p> <font color="#0000ff">        Pointer& wrapped()<br />        {<br />            return ptr_;<br />        }</font> </p> <p> <font color="#0000ff">        const Pointer& wrapped() const<br />        {<br />            return ptr_;<br />        }</font> </p> <p> <br /> <font color="#0000ff">private:<br />        Pimpl(const Pimpl&);<br />        Pimpl& operator=(const Pimpl&);</font> </p> <p> <font color="#0000ff">        Pointer ptr_;<br />};</font> </p> <div>可以看到Q这个类用了上面?font color="#0000ff">ConstPropPtr</font><font color="#000000">从而对象有了const属性的传递。其他的Q实际上Q帮你操作了new,?/font><font color="#0000ff">ConstPropPtr</font><font color="#000000">里释放,有点RAII的味道,剩下的完全模拟保存的指针的行为,即implT的实玎ͼ从而其能正确的操作对象?/font></div> <div> <img src="http://blog.sina.com.cn/images/face/022.gif" />睡死了,早早l束</div> <div>                                                 alex_yuu</div> <img src ="http://www.shnenglu.com/agerlis/aggbug/18644.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/agerlis/" target="_blank">agerlis</a> 2007-02-11 15:52 <a href="http://www.shnenglu.com/agerlis/archive/2007/02/11/18644.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>W?ơ来Q发W?份脓Q我叫alex,是刚毕业的菜菜鸟Q大家请多关?/title><link>http://www.shnenglu.com/agerlis/archive/2007/02/11/18635.html</link><dc:creator>agerlis</dc:creator><author>agerlis</author><pubDate>Sun, 11 Feb 2007 07:32:00 GMT</pubDate><guid>http://www.shnenglu.com/agerlis/archive/2007/02/11/18635.html</guid><wfw:comment>http://www.shnenglu.com/agerlis/comments/18635.html</wfw:comment><comments>http://www.shnenglu.com/agerlis/archive/2007/02/11/18635.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/agerlis/comments/commentRss/18635.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/agerlis/services/trackbacks/18635.html</trackback:ping><description><![CDATA[我的msn:agerlis@163.com<br />我的email:agerlis@163.com<br />我的qq:350457656<img src ="http://www.shnenglu.com/agerlis/aggbug/18635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/agerlis/" target="_blank">agerlis</a> 2007-02-11 15:32 <a href="http://www.shnenglu.com/agerlis/archive/2007/02/11/18635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.langmyc.cn" target="_blank">Ʒþþþþþ</a>| <a href="http://www.cnwowshell.cn" target="_blank">һþ</a>| <a href="http://www.vnaiman.cn" target="_blank">ɫۺϾþ88ɫۺ </a>| <a href="http://www.buniaowan.cn" target="_blank">޾ƷþëƬ</a>| <a href="http://www.jrbjh.cn" target="_blank">ŷսþþþþþþ</a>| <a href="http://www.xiewanliang.cn" target="_blank">ŷ߽˾þ</a>| <a href="http://www.ssxgsl.cn" target="_blank">޹Ʒ˾þ</a>| <a href="http://www.cutfat.com.cn" target="_blank">Ļ޹˾þþƷ</a>| <a href="http://www.odcb.cn" target="_blank">þþƷһ99</a>| <a href="http://www.mtdo.cn" target="_blank">þþ뾫Ʒҹ</a>| <a href="http://www.fqgjz.cn" target="_blank">WWWAVþþӰƬ</a>| <a href="http://www.xinashop.cn" target="_blank">պþëƬ </a>| <a href="http://www.safaen.cn" target="_blank">ƷŮþþ</a>| <a href="http://www.dr-knoell-consult.com.cn" target="_blank">þþþþþ޾Ʒ</a>| <a href="http://www.vauban.cn" target="_blank">ղþøŷһ</a>| <a href="http://www.ljvs.cn" target="_blank">޾Ʒtvþþþþþþþ</a>| <a href="http://www.vocard.cn" target="_blank">AVþþþòվ</a>| <a href="http://www.hiinterface.cn" target="_blank">ҹþAAAAAëƬѿ</a>| <a href="http://www.jsshunfu.com.cn" target="_blank">ҹѸþӰԺ</a>| <a href="http://www.228456.cn" target="_blank">ݺɫþþۺ</a>| <a href="http://www.upvd.cn" target="_blank">޹˾þۺһ</a>| <a href="http://www.hadonghoon.cn" target="_blank">޹ŷۺϾþ</a>| <a href="http://www.xzxms.cn" target="_blank">ҹҹþݺ</a>| <a href="http://www.west126.cn" target="_blank">69Ʒþþþ9999</a>| <a href="http://www.jrbjh.cn" target="_blank">þ91Ʒþ91ۺ</a>| <a href="http://www.xiaoxyl.cn" target="_blank">þþƷһԡ</a>| <a href="http://www.yzx777.cn" target="_blank">뾫ƷþɪӰ</a>| <a href="http://www.xiewanliang.cn" target="_blank">þóӰԺƷ777</a>| <a href="http://www.air-ticket.cn" target="_blank">Ʒþþþ㽶</a>| <a href="http://www.0576yes.cn" target="_blank">ɫۺϾþĻ</a>| <a href="http://www.pkx9.cn" target="_blank">þþƷþý</a>| <a href="http://www.tnbzjrzhl.cn" target="_blank">ѹ99þþ㽶</a>| <a href="http://www.lafei02.cn" target="_blank">¾þþþa</a>| <a href="http://www.airesou.cn" target="_blank">ɫվ޷ľþò </a>| <a href="http://www.jsjingkou.cn" target="_blank">Ʒþþþһ </a>| <a href="http://www.cqhxdj.com.cn" target="_blank">Ʒþþþ</a>| <a href="http://www.caifu580.cn" target="_blank">þ޹Ʒһ</a>| <a href="http://www.97xxri.cn" target="_blank">þþž޾Ʒ</a>| <a href="http://www.qlmoban.cn" target="_blank">۲ӰԺþ99</a>| <a href="http://www.huating.net.cn" target="_blank">㽶þþþ</a>| <a href="http://www.pz897.cn" target="_blank">þþþþ޾Ʒ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>