65.9K
CodeProject 正在变化。 阅读更多。
Home

C++0x 动态消息传递

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.53/5 (12投票s)

2010 年 11 月 26 日

CPOL

2分钟阅读

viewsIcon

39733

downloadIcon

384

C++0x 动态消息传递(类似 Objective-C)

引言

有时,像 Objective-C 那样拥有动态消息传递是有用的。下面提供的简短头文件允许任何类包含一个动态消息映射,该映射可用于动态地将方法添加到对象中。

背景

Objective-C 被认为比 C++ 更灵活,因为它允许一种称为 消息传递 的动态分发形式。

消息传递是一种动态分发形式,它不需要实现特定的接口类型。当向目标对象发送消息时,编译器不知道该对象是否可以处理该消息。只有在程序执行期间才能发现对接口的符合性。

消息传递非常灵活,因为它不需要大量的计划。Objective-C 因其比 C++ 更灵活的特性而受到赞扬。本文演示了如何在标准的 C++ (c++0x) 中轻松实现相同的功能。

Using the Code

使用这段代码非常简单。需要遵循以下步骤:

  • 在您的项目中包含头文件 "mp_object.hpp"。
  • 从类 mp_object 继承。
  • 使用方法 'add_method' 将动态方法添加到您的对象中。

为了添加对象的方法,您需要一个原型函数。原型函数可以是任何独立的函数。以下代码是声明原型和将动态方法添加到代码中的示例:

#include <iostream>
#include "mp_object.hpp"
using namespace std;

//prototype method
void draw() {}

//prototype method
void setColor(int color) {}

//rectangle
class rect : public mp_object {
public:
    //constructor
    rect() {
        add_method(::draw, &rect::draw);
        add_method(::setColor, &rect::setColor);
    }

    //draw
    void draw() {
        cout << "rect\n";
    }

    //set color
    void setColor(int color) {
        cout << "rect color = " << color << "\n";
    }
};

//circle
class circle : public mp_object {
public:
    //constructor
    circle() {
        add_method(::draw, &circle::draw);
        add_method(::setColor, &circle::setColor);
    }

    //draw
    void draw() {
        cout << "circle\n";
    }

    //set color
    void setColor(int color) {
        cout << "circle color = " << color << "\n";
    }
};

您可以像这样动态地调用对象:

int main() {
    rect r;
    circle c;

    r.invoke(draw);
    c.invoke(draw);

    r.invoke(setColor, 10);
    c.invoke(setColor, 20);

    return 0;
}

以上输出是:

rect
circle
rect color = 10
circle color = 20

实现细节

实现非常简单。类 mp_object 具有原型函数指针到方法指针的哈希映射。当调用方法时,从原型函数检索适当的方法指针并执行。

为了最大限度地减少内存使用,类 mp_object 使用写时复制:许多实例之间共享一个方法映射,直到它被修改。如果被修改,则复制方法映射并将更改应用于副本。

mp_object 代码是 39 行代码,这要归功于 C++0x。如果使用较早版本的 C++,则需要大量的样板代码来做基本相同的事情。

这段代码可以轻松地扩展到新的功能中;例如,查询对象是否支持特定方法或一种反射形式(与宏结合)。不过,这些超出了本文的范围。

历史

  • 2010 年 11 月 26 日:初始发布
© . All rights reserved.