C++ 的动态消息传递





4.00/5 (1投票)
C++ 的动态消息传递。
引言
像 Smalltalk 和 Objective-C 这样的编程语言被认为比 C++ 更灵活,因为它们支持动态消息传递。C++ 不支持动态消息传递;它只支持静态消息传递:当调用对象的某个方法时,目标对象必须具有被调用的方法;否则,编译器会输出错误。
虽然 C++ 的消息传递方式比 Smalltalk 或 Objective-C 的方式快得多,但有时需要 Smalltalk 或 Objective-C 的灵活性。 这篇文章展示了如何在 C++ 中以最少的代码实现动态消息传递。
背景
C++ 通过 虚表 (vtables) 来实现消息传递。
Smalltalk 和 Objective C 使用方法映射 (method map) 来实现相同的结果。
示例
提供的头文件包含动态消息传递的实现。为了向对象添加动态消息传递能力,必须执行以下操作:
- 声明一个全局函数,作为消息的签名。
- 从
dmp::object
继承。 - 在类构造函数中,使用
add_message
方法向对象添加一个或多个消息。 - 使用函数
invoke(signature, ...parameters)
向对象发送消息。
这是一个例子。
//the dynamic-message-passing header #include "dmp.hpp" //the message signature std::string my_message(int a, double b) { return ""; } //a class that accepts messages dynamically class test : public dmp::object { public: test() { add_message(&::my_message, &test::my_message); } std::string my_message(int a, double b); }; int main() { test t; std::string s = t.invoke(&::my_message, 10, 3.14); }
工作原理
每个对象包含指向映射的共享指针。映射的键是指向消息签名的指针。映射的值是指向内部消息结构的指针,该结构保存着要调用的方法的指针。
当调用一个方法时,从映射中检索适当的消息结构,并使用 this
作为目标对象,调用消息结构中存储的对象的该方法。
出于效率的原因,内部使用的映射是无序的。
为了提高效率,对象的消息映射也在对象之间共享。当修改消息映射时,如果它不是唯一的,则会对其进行复制,即应用写时复制模式。
只有当不同线程在查找消息映射时,消息映射没有被修改,代码才是线程安全的。如果修改了消息映射,则任何线程都不应同时向对象发送消息。
代码使用 boost 库是因为:
- 无序映射;使用了类
boost::unordered_map
。 - 预处理器;用于自动为不同数量的参数构建代码。
- 共享指针;用于内部内存管理。