首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C++中模拟CLOS : and,:after,and:CLOS

在C++中模拟CLOS : and,:after,and:CLOS
EN

Stack Overflow用户
提问于 2011-07-08 09:09:38
回答 3查看 434关注 0票数 2

CLOS有一个很好的概念:前、后和:外周方法。

在主方法之前调用

  • :在主方法之前调用;
  • 在主方法之后调用;

方法围绕:before+primary+:after序列调用。

“前”、“后”和“:循环”方法是链式的,而不是重写的。假设父类和子类都定义了foo方法和: parent方法。子方法的foo方法重写父方法的foo方法,但在调用该重写方法之前,子方法和父方法都会被调用。

Python装饰器提供了类似于CLOS :的东西。在C++中没有这样的东西。它必须手工轧制:

代码语言:javascript
复制
class Child : public Parent {
    virtual void do_something (Elided arguments) {
        do_some_preliminary_stuff();
        Parent::do_something (arguments);
        do_some_followup_stuff();
    }
};

缺点:

对于某些人来说,这是一种反模式。paradigm.

  • What

  • 要求我明确指定父类。如果由于父级不覆盖do_something而需要调用外祖父母,则需要类的扩展程序遵循相同的。

当我使用口味(CLOS的前身)时,我发现这些概念非常方便。我已经在几个地方使用了上面的解决方法,也有一些人将其作为反模式提出了挑战。(其他人在其他地方也模仿过,因此这种嘲讽并不是普遍的。)

问题是:这在C++中被认为是一种反模式吗?还有更好的解决办法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-08 09:53:29

这是我能做的,但还是有点丑。

基本上,我把实际的工作放在一个单独的钩子中,这样在处理方法中就没有调用前/后挂钩了。在继承链中,您可以完全控制是否要添加预/后挂钩和钩子调用的顺序(在子挂钩之前或之后调用父钩子)。

代码语言:javascript
复制
#include <iostream>
#define C(s) std::cout << s << std::endl;

class Parent {
    public:
    virtual void do_something(int arg) {
        do_some_pre_hook();
        do_some_hook(arg);
        do_some_post_hook();
    }
    virtual void do_some_pre_hook() {
        C("parent pre_hook");
    }
    virtual void do_some_post_hook() {
        C("parent post_hook");
    }
    virtual void do_some_hook(int arg) {
        //this is where you actually do the work
    }
};

class Child : public Parent {
    public:
    typedef Parent super;

    virtual void do_some_pre_hook() {
        super::do_some_pre_hook();
        C("Child pre_hook");
    }
    virtual void do_some_post_hook() {
        super::do_some_post_hook();
        C("Child post_hook");
    }
};

class GrandChild : public Child {
    public:
    typedef Child super;

    virtual void do_some_pre_hook() {
        super::do_some_pre_hook();
        C("GrandChild pre_hook");
    }
    virtual void do_some_post_hook() {
        super::do_some_post_hook();
        C("GrandChild post_hook");
    }
    virtual void do_some_hook(int arg) {
        //this is where you actually do the work
        C("GrandChild hook");
    }
};

int main() {
    GrandChild gc;
    gc.do_something(12);
}

注意事项:理想情况下,您可以使用AOP c++编译器或编译器扩展来执行这样的任务,但上次我尝试时它并不是很稳定……

票数 1
EN

Stack Overflow用户

发布于 2011-07-08 10:15:08

使用(std/boost)::shared_ptr,您可以很好地了解这方面的基础知识。有关详细信息,请参阅此处:http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/sp_techniques.html#wrapper

要获得您提到的继承行为,只需要前缀/后缀函数调用父类中的前缀/后缀函数。

票数 2
EN

Stack Overflow用户

发布于 2011-07-08 09:39:05

我并不认为这与其他语言相同或类似,但我认为非虚拟界面()成语适用于您的问题:

代码语言:javascript
复制
class parent {
public:
    void foo()
    {
        before_foo();
        do_foo();
        after_foo();
    }

protected:
    // you can make those pure virtual with an implentation, too
    virtual void before_foo() { ... }
    virtual void do_foo() { ... }
    virtual void after_foo() { ... }
};

class child: public parent {
protected: // or private
    void before_foo() { ... }
    void do_foo() { ... }
    // must provide a dummy after_foo that delegates to parent::after_foo
    // if it is pure virtual in the parent class
};

在调用p.foo()时,总是调用最派生的before_fooafter_foodo_foo

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6622290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档