How to add code at the entry of every function?

前端 未结 6 855
悲哀的现实
悲哀的现实 2020-12-05 15:03

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 test         


        
6条回答
  •  伪装坚强ぢ
    2020-12-05 15:26

    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 
    
    template
    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;
    }
    

    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 
    
    template
    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 method;
    };
    
    int main() {
       FooWrapped f;
       f.otherstuff();
       f.method();
       return 0;
    }
    

    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.

    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 
    #include 
    
    template 
    struct Wrapper {
      template  
      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)...);
        }
    
        Ret operator()(Args&& ...args) const {
          return ((inst).*(F))(std::forward(args)...);
        }
      };
    };
    
    template 
    struct deduce_memfn;
    template 
    struct deduce_memfn {
      template  
      static typename Wrapper::template MemberFn make();
    };
    
    template 
    decltype(deduce_memfn()) deduce(T);
    
    template 
    struct workaround : T {}; // Clang 3.0 doesn't let me write decltype(deduce(&Class::Method))::make...
    
    #define WRAP_MEMBER_FN(Class, Method) decltype(workaround::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";
    }
    

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

提交回复
热议问题