深圳夜归人

繁华的都市,有谁记得我们的脚步?

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

2005-07-28 15:49  重写了所有代码,不再把对象指针和函数指针转换为void*,而是保留原类型,通过虚函数让编译器来完成绑定。新版本下载

2005-07-27 10:36  返回值为void的特化版本改为直接循环,其它返回值的处理方式不变,依旧是Ret r = call(...); for (;;;) ret = call (...);这种方式。以后有好的方案再修改。

2005-07-26 21:36  修正G++编译的版本段错误(感谢 问题男),经初步测试没有发现问题。

2005-07-26 09:51  修正call函数中缺少typename的错误(感谢
bcpl ),增加了Makefile(需要系统中安装有python),段错误的大问题还没有解决(确认VC8中不存在这问题)。

2005-07-25 23:55  修正代码生成器脚本中的2处错误,修正处理返回值的失误,增加测试代码。


相比前一版本,修改了以下几点(下标从0开始:))
0、类名改为Delegate。
1、采用Delegate < int& (const stirng&, float) > d这样的语法,更直观(学boost::function的)。
2、可以绑定仿函数了。
3、支持最多26个参数。。。(使用python脚本生成的,用宏太累)
4、如果返回值不是void,那么当委托没有绑定任何对象时,调用将抛出DelegateNotHandled异常。
5、支持=、+=、()操作符。
6、支持绑定委托对象。因为委托对象本身也是个仿函数,所以这里把它按仿函数来处理了。



重要提示:
0、Delegate.h文件是由generator.py读取其它3个文件,并替换其中定义的格式化字符串来生成的。
1、不要用它来绑定多继承类的成员函数。

扩充话题:
和boost::function比较,本文的Delegate类型要求比较严格,我认为这是好事。boost::function可以定义一个int(int)类型的function,但绑定一个short(double)类型的函数,实际并不是好事,我认为。

Delegate解决这类问题的方法是使用Adapter,这里给一个例子:

short funcB (double d)
{
    
return (short)d;
}

struct FuncA2FuncBAdapter
{
    Delegate 
<short(double)> adapter;
    
int operator ( ) (int n)
    {
        
return (int)adapter ((double)n);
    }
};

int main ()
{
    Delegate 
<int(int)> d_test;
    FuncA2FuncBAdapter adp;
    d_test 
+= adp;
    adp.adapter 
+= funcB;
    d_test (
3);
    
return 0;
}

这样可以明确地把强制转型的责任交给程序员,而不是编译器偷偷的做。

用Adapter还可以做更复杂的,下面这个boost::function就不能直接转了:

pair<shortshort> funcB (double a, int b)
{
    
return make_pair((short)a, (short)b);
}

struct FuncA2FuncBAdapter
{
    Delegate 
<pair<shortshort>(doubleint)> adapter;
    
int operator ( ) (int n)
    {
        
return (int)adapter ((double)n, n+5).first;
    }
};

int main ()
{
    Delegate 
<int(int)> d_test;
    FuncA2FuncBAdapter adp;
    d_test 
+= adp;
    adp.adapter 
+= funcB;
    d_test (
3);
    
return 0;
}

另一个差别是本文的Delegate类是多分派的。

下载:
https://files.cnblogs.com/cpunion/Delegate.rar

感谢:
  问题男 bcpl 刘未鹏(blog中关于函数类型的讲解)。


刚在comp.lang.c++@googlegroups.com上看到的一个CallBack类,摘录在此。

// file sltest.h
#ifndef SLTEST_H
#define SLTEST_H

class CallbackBase
{
public:
    
virtual void operator()() const { };
    
virtual ~CallbackBase() = 0;
};

CallbackBase::
~CallbackBase() { }
template
<typename T>
class Callback : public CallbackBase
{
public:
    typedef 
void (T::*F)();
    Callback( T
& t, F f ) : t_(&t), f_(f) { }
    
void operator()() const { (t_->*f_)(); }
private:
    T
* t_;
    F  f_;
};

template
<typename T>
Callback
<T> make_callback( T& t, void (T::*f) () )
{
    
return Callback<T>( t, f );
}
posted on 2005-07-25 17:51  cpunion  阅读(3336)  评论(32编辑  收藏  举报