美文网首页
2.1 点切

2.1 点切

作者: liril | 来源:发表于2016-03-26 21:45 被阅读49次

    2.1 点切

    AspectC++的方向以模块化的方式实现了横切关注点。出于这个考虑,AspectC++语言中最重要的元素是点切。点切描述了一系列结合点来决定什么情况下某一方向应该有作用。因此每个结合点既可以指代函数、属性、类型、变量或者结合点可访问的点,这样这一情况可以实例化事件来实现设计好的代码位置。根据不同的点切,他们将在编译时或者运行时被估算。

    2.1.1 匹配表达式

    AspectC++中有两种点切:代码点切和名称点切。名称点切描述了一系列(静态)已知程序入口,如类型、属性值、函数、变量和命名空间。所有的名称点切是基于匹配表达式的。匹配表达式可以被理解为搜索模式。这种搜索模式中,特殊字符“%”被解释成名称的通配符或标示符的一部分。特殊字符序列“...”匹配函数标示符的任意数量的参数,或者一个认证名称的任意数量的作用域。匹配表达式是带引号的字符串。

    例:匹配表达式(名称点切)

    "int C::%(...)"

    匹配类C中所有返回int的成员函数

    "%List"

    匹配任意以“List”结尾的类、结构体、共用体或枚举

    "% printf(const char *, ...)"

    匹配函数printf(在全局作用域中定义)拥有至少一个const char *类型的参数,并返回任意类型

    "const %& ...::%(...)"

    匹配返回常量对象引用的所有函数

    匹配表达式根据定义的作用域、类型和名称选择程序入口。关于匹配表达式语义的详细介绍将在第三节中介绍。附录B中展示了定义正确句法的匹配表达式。

    2.1.2 点切表达式

    另一种点切,代码点切,描述了程序控制流中点集的交集。代码点切可以指代函数调用或执行的点。他们只能在名称点切的前提下创建,这是因为所有AspectC++支持的结合点需要至少一个定义的名称。它通过调用实现定义的点切函数实现,点切函数是以点切作为参数的点切表达式。within(点切)就是这样一个点切函数的例子,它过滤了所有在给定点切的函数和类的结合点。

    名称和代码点切可以在点切表达式中用代数操作符“&&”,“||”和“!”结合在一起。

    例:点切表达式

    "%List" && !derived("Queue")

    描述了所有不是从类Queue派生而来的以“List”结尾的类集

    call("void draw()") && within("Shape")

    描述了类Shape中调用了函数draw的方法集

    2.1.3 结合点类型

    除了AspectC++支持的两点类型的点切,还有两点类型的结合点。基于一小段代码片段可以清楚的分辨这两种类型的区别和联系。

    class Shape;
    void draw(Shape&);
    
    namespace Circle {
        typedef int PRECISION;
    
        class S_Circle : public Shape {
            PRECISION m_radius;
        public:
            ...
            void radius(PRECISION r) { m_radius = r; }
        };
    
        void draw(PRECISION r) {
            S_Circle circle;
            circle.radius(r);
            draw(circle);
        }
    }
    
    int main() {
        Circle::draw(10);
        return 0;
    }
    

    代码结合点用来组成代码点切,名称结点(如名称)用来组成名称切点。下面的图1展示了代码片段的一些结合点以及它们如何关联的。

    图1 结合点它们的关系

    每一个执行结合点说可执行函数的名称相关联。纯虚函数并不能执行。因此,执行结合点的建议代码永远不会为这种函数触发。然而,这种函数的调用,如以此函数为目标的调用结合点,是完全有可能的。

    每一个调用结合点通过两个名称关联:函数调用的原函数和目标函数的名称。因为统一函数可能存在多个函数调用,每一个函数名称可以和一堆调用结合点关联。一个构造结合点表示当是咧创建时类指定执行的指令序列。类似的,析构结合点表示对象析构。

    2.1.4 点切声明

    AspectC++通过点切声明来提供名称点切表达式的能力。这使得在不同的程序中复用点切表达式成为可能。在所有C++声明允许的地方都允许使用点切声明。因此常规的C++名称查询和继承规则同样适用于点切声明。

    点切声明由关键词pointcut引出。

    例:点切声明

    pointcut lists() = derived("List");

    lists现在可以在程序的任意地方使用,用来指代`derived("List")

    而且,点切声明可以用来定义纯虚点切。这使得可复用虚方向成为可能,这将在2.4节讨论。除了在pointcut后跟着virtual关键词,点切表达式为“0”外,纯虚点切声明和普通的点切声明语法一样。

    *例:纯虚点切声明

    pointcut virtual methods() = 0;

    methods是一个纯虚点切,必须在派生方向中重新定义来指向真正的点切表达式。

    相关文章

      网友评论

          本文标题:2.1 点切

          本文链接:https://www.haomeiwen.com/subject/fjwdlttx.html