您现在的位置: 天极网 > 开发频道 > 使用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订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868
版权声明 在线提交意见反馈 渝ICP证B2-20030003号
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|IT商网|52PK游戏网|IT分众