我想在每次函数调用之前添加一些代码来做一些检查。我知道的唯一方法是:
#define SOME_CODE printf("doing something...");
class testObject
{
void function1()
{
 SOME_CODE
 ...
}
void function2()
{
 SOME_CODE
 ...
}
}有没有更干净的方法来实现这一点?我正在寻找一种方法,这样我就不需要手动为每个函数添加"SOME_CODE“。
发布于 2011-02-23 01:00:10
根据您希望实现的结果,您可以使用包装实际调用的函数器对象在C++中创建一些东西(对于自由函数或静态成员函数来说很容易),例如:
#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可变模板或大量重载。让它与成员函数很好地协同工作也更加繁琐。
我也为成员函数勾勒出了一种(非侵入式的)方式:
#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;
}您也可以跳过私有继承和using来公开非包装方法,但是您需要小心析构函数,如果这样做,很容易被意外绕过。(例如,隐式强制转换以引用基类)。非侵入式方式也仅限于公共接口,也不能用于内部调用。
使用C++11,您可以获得完美的转发,还可以将包装对象的构造简化为一个简单的宏,该宏获取类和成员函数名并为您推导出其余部分,例如:
#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测试的。
发布于 2011-02-23 01:10:23
对于gcc来说,对于MSVC也有一个类似的解决方案,其他人发布了一个答案:
#include <iostream>
int depth=-1;
extern "C" {
    void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));
    void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function));
    void __cyg_profile_func_enter (void *func,  void *caller)
    {
        depth++;
    }
    void __cyg_profile_func_exit (void *func, void *caller)
    {
        depth--;
    }
}
class Foo {
public:
    void bar() {
        std::cout << "bar: " << depth << std::endl;
    }
};
int main() {
    Foo f;
    f.bar();
    return 0;
}使用g++ -Wall -Wextra -finstrument-functions编译。但是要注意,不要从工具钩子中调用插入指令的函数!(有关排除事物的方法,请参阅手册页)
发布于 2011-02-23 00:49:43
这取决于您使用的编译器。我使用的是DevStudio 2005,在联机帮助中有这个编译器命令行选项:
钩子/Gh (启用_penter钩子功能)
导致在每个方法或函数开始时调用_penter函数。
_penter函数不是任何库的一部分,您可以为_penter提供定义。
除非您计划显式调用_penter,否则不需要提供原型。该函数必须看起来像具有以下原型,并且必须在进入时推送所有寄存器的内容,并在退出时弹出未更改的内容:
void __declspec(naked) _cdecl _penter( void );https://stackoverflow.com/questions/5081123
复制相似问题