CLOS有一个简洁的概念:before,:after和:around around。
:before,:after和:around方法被链接而不是被覆盖。假设父类和子类都定义了一个foo方法,并且:在foo方法之前。子进程的foo方法会覆盖父进程的foo方法,但会覆盖子进程和父进程:在调用这个重写方法之前调用foo方法之前。
Python装饰器提供类似于CLOS的东西:around方法。在C ++中没有这样的东西。它必须手工轧制:
class Child : public Parent {
virtual void do_something (Elided arguments) {
do_some_preliminary_stuff();
Parent::do_something (arguments);
do_some_followup_stuff();
}
};
缺点:
do_something
,以及多重继承怎么办?当我使用Flavors(CLOS的前身)时,我发现这些概念非常方便。我在一些地方使用了上述解决方法,有些人将其作为反模式挑战。 (其他人已在其他地方模仿它,因此嘲笑并不普遍。)
问题:这是否被认为是C ++中的反模式,是否有更好的解决方法?
答案 0 :(得分:2)
你可以使用(std/boost)::shared_ptr
很好地掌握这个基础知识。有关详细信息,请参阅此处:http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/sp_techniques.html#wrapper
获取您提到的继承行为只需要前缀/后缀函数来调用父类中的前缀/后缀函数。
答案 1 :(得分:1)
我并不是说这与其他语言相同或相当,但我认为非虚拟接口惯用法适用于您的问题:
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_foo
,after_foo
和do_foo
。
答案 2 :(得分:1)
这是我能做的,但它仍然有点难看。
基本上我把实际的工作放在一个单独的钩子里,所以你没有在处理方法中调用pre / post钩子。在继承链中,您可以完全控制是否要添加前/后挂钩以及挂钩调用的顺序(在子挂钩之前或之后调用父挂钩)。
#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 ++编译器或编译器扩展,但是上次我尝试它时它不太稳定......