如何在每个函数的入口处添加代码? [英] How to add code at the entry of every function?

查看:180
本文介绍了如何在每个函数的入口处添加代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在每个函数调用之前添加一些代码来做一些检查。我知道的唯一方法是:

I want to add some code before every function call to do some checking. The only way I know is:

#define SOME_CODE printf("doing something...");

class testObject
{
void function1()
{
 SOME_CODE
 ...
}
void function2()
{
 SOME_CODE
 ...
}
}

有没有更清洁的方法来实现这一点?我正在寻找一个方法,所以我没有手动添加SOME_CODE到每个函数。

Is there a cleaner way to achieve this? I'm looking for a method so I don't have add "SOME_CODE" to every function manually.

推荐答案

你希望实现这样的结果,你可以在C ++中使用包装真正调用的函子对象来做一些事情(很容易实现自由函数或静态成员函数),例如:

Depending on what you're hoping to achieve as a result of this you can sort of make something (easily enough for free functions or static member functions) in C++ with functor objects which wrap real calls, e.g.:

#include <iostream>

template<void f(void)>
struct Wrap {
   void operator()() const {
      std::cout << "Pre call hook" << std::endl;
      f();
   }
};

namespace {
   void test_func() {
      std::cout << "Real function" << std::endl;
   }
}

const Wrap<&test_func> wrapped_test_func = {};

int main() {
   wrapped_test_func();
   return 0;
}

很明显,这需要一些更通用的工作。 C ++ 0x可变参数模板或批次的重载。

Clearly this needs some more work to be generic enough e.g. C++0x variadic templates or lots of overloads. Making it work nicely with member functions is also more fiddly.

我已经为成员函数绘制了一个(非侵入)方法的大纲:

I've sketched an outline for a (non-intrusive) way of doing this for member functions too:

#include <iostream>

template<class C, void (C::*F)()>
class WrapMem {
   C& inst;
public:
   WrapMem(C& inst) : inst(inst) {}

   void operator()() {
      std::cout << "Pre (method) call hook" << std::endl;
      ((inst).*(F))();
   }

   void operator()() const {
      std::cout << "Pre (method, const) call hook" << std::endl;
      ((inst).*(F))();
   }
};

class Foo {
public:
   void method() { std::cout << "Method called" << std::endl; }
   void otherstuff() {}
};

class FooWrapped : private Foo  {
public:
   FooWrapped() : method(*this) {}
   using Foo::otherstuff;
   WrapMem<Foo,&Foo::method> method;
};

int main() {
   FooWrapped f;
   f.otherstuff();
   f.method();
   return 0;
}

您也可以跳过私有继承和 / code>暴露非包装的方法,但你需要小心的析构函数,很容易意外绕过,如果你这样做。 (例如用于引用base的隐式转换)。非侵入方式也限于只对公共接口工作,也不对内部呼叫工作。

You could also skip the private inheritance and using to expose non-wrapped methods, but you need to be careful about destructors and it's easy to accidentally bypass if you do that. (e.g. implicit cast for reference to base). The non-intrusive way is also limited to only working for the public interface and not for internal calls either.

使用C ++ 11,您可以获得完美的转发,并将包装对象的构造减少到一个简单的宏,它接受类和成员函数名称,并推导出其余为您,例如:

With C++11 you can get perfect forwarding and also reduce the construction of the wrapping objects to a simple macro that takes the class and member function name and deduces the rest for you, e.g.:

#include <iostream>
#include <utility>

template <typename Ret, typename ...Args>
struct Wrapper {
  template <class C, Ret (C::*F)(Args...)> 
  class MemberFn {
    C& inst;
  public:
    MemberFn(C& inst) : inst(inst) {}
    MemberFn& operator=(const MemberFn&) = delete;

    Ret operator()(Args&& ...args) {
      return ((inst).*(F))(std::forward<Args>(args)...);
    }

    Ret operator()(Args&& ...args) const {
      return ((inst).*(F))(std::forward<Args>(args)...);
    }
  };
};

template <typename T>
struct deduce_memfn;
template <typename C, typename R, typename... Args>
struct deduce_memfn<R (C::*)(Args...)> {
  template <R(C::*F)(Args...)> 
  static typename Wrapper<R, Args...>::template MemberFn<C, F> make();
};

template <typename T>
decltype(deduce_memfn<T>()) deduce(T);

template <typename T>
struct workaround : T {}; // Clang 3.0 doesn't let me write decltype(deduce(&Class::Method))::make...

#define WRAP_MEMBER_FN(Class, Method) decltype(workaround<decltype(deduce(&Class::Method))>::make<&Class::Method>()) Method = *this

class Foo {
public:
  Foo(int);
  double method(int& v) { return -(v -= 100) * 10.2; }
  void otherstuff();
};

class WrappedFoo : private Foo {
public:
  using Foo::Foo; // Delegate the constructor (C++11)
  WRAP_MEMBER_FN(Foo, method);
  using Foo::otherstuff;
};

int main() {
  WrappedFoo f(0);
  int i = 101;
  std::cout << f.method(i) << "\n";
  std::cout << i << "\n";
}

(注意:这种扣除不适用于重载)
这是用Clang 3.0测试的。

(Note: this deduction won't work with overloads) This was tested with Clang 3.0.

这篇关于如何在每个函数的入口处添加代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆