"挂钩"是指非侵入性地覆盖函数行为的能力.一些例子:
我在各种编程语言和库中看到了不同的实现:
method_missing%exception关键字用于包装try/catch块中的所有函数,可以(ab)用于挂钩我的问题是:
Dav*_*e S 13
如果您正在讨论在函数体之前/之后调用新方法而不更改函数体,则可以将其基于此,它使用自定义shared_ptr删除器来触发后体函数.它不能用于try/catch,因为之前和之后需要使用这种技术的单独功能.
此外,下面的版本使用shared_ptr,但使用C++ 11,你应该可以使用它unique_ptr来获得相同的效果,而无需每次使用它时创建和销毁共享指针的成本.
#include <iostream>
#include <boost/chrono/chrono.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/shared_ptr.hpp>
template <typename T, typename Derived>
class base_wrapper
{
protected:
typedef T wrapped_type;
Derived* self() {
return static_cast<Derived*>(this);
}
wrapped_type* p;
struct suffix_wrapper
{
Derived* d;
suffix_wrapper(Derived* d): d(d) {};
void operator()(wrapped_type* p)
{
d->suffix(p);
}
};
public:
explicit base_wrapper(wrapped_type* p) : p(p) {};
void prefix(wrapped_type* p) {
// Default does nothing
};
void suffix(wrapped_type* p) {
// Default does nothing
}
boost::shared_ptr<wrapped_type> operator->()
{
self()->prefix(p);
return boost::shared_ptr<wrapped_type>(p,suffix_wrapper(self()));
}
};
template<typename T>
class timing_wrapper : public base_wrapper< T, timing_wrapper<T> >
{
typedef base_wrapper< T, timing_wrapper<T> > base;
typedef boost::chrono::time_point<boost::chrono::system_clock, boost::chrono::duration<double> > time_point;
time_point begin;
public:
timing_wrapper(T* p): base(p) {}
void prefix(T* p)
{
begin = boost::chrono::system_clock::now();
}
void suffix(T* p)
{
time_point end = boost::chrono::system_clock::now();
std::cout << "Time: " << (end-begin).count() << std::endl;
}
};
template <typename T>
class logging_wrapper : public base_wrapper< T, logging_wrapper<T> >
{
typedef base_wrapper< T, logging_wrapper<T> > base;
public:
logging_wrapper(T* p): base(p) {}
void prefix(T* p)
{
std::cout << "entering" << std::endl;
}
void suffix(T* p)
{
std::cout << "exiting" << std::endl;
}
};
template <template <typename> class wrapper, typename T>
wrapper<T> make_wrapper(T* p)
{
return wrapper<T>(p);
}
class X
{
public:
void f() const
{
sleep(1);
}
void g() const
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main () {
X x1;
make_wrapper<timing_wrapper>(&x1)->f();
make_wrapper<logging_wrapper>(&x1)->g();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您可以利用特定于编译器的功能,例如GCC的-finstrument-functions.其他编译器可能具有类似的功能.有关其他详细信息,请参阅此问题.
另一种方法是使用类似Bjarne Stroustrup的函数包装技术.