首页产品库评测行情新闻|手机数码笔记本台式机DIY硬件数字家庭数码相机办公外设|软件下载游戏开发|社区

更多

数码相机
MP4
LCD
机箱
音箱

天极网 > 开发频道>使用C++深入研究.NET委托与事件

使用C++深入研究.NET委托与事件

2004-06-07 09:42作者:翻译 曾毅出处:论坛责任编辑:方舟

  创建一个委托类

  拥有类型安全成员函数指针是我们效仿.NET功能的第一部。尽管如此,单独的成员函数指针是毫无用处的 — 你总是需要一个类的实例;委托对象同时保持在两边,使得调用成员函数非常方便。我们接着上面的例子续写下面的代码:

struct StrLen_Delegate
{
typedef size_t (Str::*MF_T)(const char*);
MF_T m_method;
Object& m_pTarget;
StrLen_Delegate(Object& o, const MF_T& mf) :
m_pTarget(&o), m_method(mf) {}

MF_T Method() const {
return m_method;
}

Object& Target() const {
return *m_pTarget;
}

size_t Invoke(const char* s) {
(m_pTarget.*m_method)(s);
}
};

void printSize2(const char* s) {
Str str;
StrLen_Delegate d(str, &Str::Len);
(void) printf("%s is %ld chars\n", s,
d.Invoke(s));
}

  有了委托类,调用成员函数变得更为简单。使用运算符代替Invoke来给这个类创建一个仿函数将使调用降为仅有d(s);为了清晰以及和.NET规定匹配,我使用Invoke。需要注意的是,类的实例是一个对象(Object)而不是Str。只要签名匹配,从Object派生来的任何一个类的成员函数指针将允许被用于创建委托。

  这个类在这个例子中使用能够工作得非常好,但是它不是非常灵活;我们必须为每一个可能的成员函数签名写一个新的委托类。.NET使用由公用语言运行时(Common Language Runtime)维护的rich type信息来解决这个问题。但这在C++中不是一个非常可行的办法,但是可以采用模板来完成类似的功能。我们不用将Invoke函数的参数设为const char* s,而是将类型指定为模板参数:

template <typename ARG1>
struct StrLen_Delegate
{
typedef size_t (Str::*MF_T)(ARG1);
// ... as above ...
size_t Invoke(ARG1 v1) {
(m_pTarget.*m_method)(v1);
}
};

  这样效果就好很多了,但是Invoke函数将只作用于单参数的成员函数。并且,委托也仅仅关心类的实例以及成员函数指针;它不是真正关心成员函数指针的细节。最后,我们很方便地就能够为成员函数指针产生一个typedef作为模版参数使用。由于一切都是由Object类派生出来的,这些细节也可以被移动到Object当中:

struct Object
{
template <typename ARG1>
struct void1_T {
typedef void (Object::*mf_t)(ARG1);
};

template <typename ARG1, typename ARG2>
void Invoke(void1_T<ARG1>::mf_t mf, ARG1 v1, ARG2) const {
(this->*mf)(v1);
}
};

template <typename CLASS>
class ObjectT : public Object {};
typedef ObjectT<void> VoidType;

  这个Object基类包含了一个typedef对应每一个成员函数签名;我使用了void返回类型来简化了很多需要做的工作。Typedef可以参照如下方式使用:

typedef Object::void1_T<std::string>::mf_t StringMF_t;

  我们使用了std::string类型的参数和void返回类型就能够非常容易地为成员函数指针创建typedef。

  程序根据附加的参数对于Invoke是跟踪计数的。这是非常必要的,因为对于所有的Invoke方法必须有同样数目的参数;重载决策基于第一个参数—成员函数指针的类型,来完成。需要注意的是大部分的.NET Framework将在委托中使用EventArgs对象来避免上述的复杂情况。你可以通过从EventArgs派生来添加额外的参数而不需要给委托添加签名。

  最后,ObjectT模版提供了一个简单的方法用来产生唯一类型,每一个类型最终是从Object派生来的。这就确保了类型安全。

  基于上面所有的内容,委托类现在就应当是如下所示的样子:

template <typename MF_T>

class DelegateT_ : public ObjectT<MF_T>
{
MF_T m_method;
Object* m_pTarget;
protected:
DelegateT_() : m_pTarget(NULL), m_method(NULL) {}
DelegateT_(Object& o, const MF_T& mf) :
m_pTarget(&o), m_method(mf) {}
public:
MF_T Method() const {
return m_method;
}
Object& Target() const {
return *m_pTarget;
}
};

  模板参数现在就是一个typedef成员函数指针(生成方法如上所示),而Invoke方法继承于Object基类。

共5页。 9 7 1 2 3 4 5 8 :

关注此文的读者还看过:

返回开发频道首页

软件频道最新更新

热点推荐

天极服务|关于我们|About us|网站律师|RSS订阅|友情合作|加入我们|天极动态|网站地图|意见反馈|MSN/QQ上看天极
Copyright (C) 1999-2012 Yesky.com, All Rights Reserved 版权所有 天极网络