tags:

views:

382

answers:

9

C++ has so much stuff that I don't know.

Is there any way to create a function within a class, that will always be called whenever any other function of that class is called? (like making the function attach itself to the first execution path of a function)

I know this is tricky but I'm curious.

+3  A: 

There is no "automatic" way to do this. You would need to add a call to the function in each class method.

crashmstr
+2  A: 

Without some insane code injection, this is not possible. However, you can of course call that function manually.

nlaq
+2  A: 

The short answer: No.

The long answer: there is no such thing in the C++ standard.

kshahar
A: 

As others have said, there is no "automatic" way to do this. As in, the C++ standard does not define a way to do this.

However, if you are going to go the route of putting a method call at the beginning of every method, I would recommend you instead store and invoke a method pointer instead. This will allow you to dynamically modify which method is being called, including none with some careful programming and setting the method to null.

jdmichal
+9  A: 

Yes. :-)

  • Wrap the object in a smart pointer
  • Invoke the object's special function automatically from the smart pointer's dereferencing operators (so that the special function is invoked whenever a client dereferences the smart pointer).
ChrisW
yes, and when someone uses this without the smart pointer and things break? And what about calling class methods from within other class methods?
crashmstr
"yes, and when ...?" Then it breaks. If someone uses this method then a client can, if they want to, go out of their way to break/bypass it. This method *does* answer the OP though, which was how to implement "making the function attach itself to the first execution path".
ChrisW
"And what about calling class methods from within other class methods?" I hadn't thought of that. But usually, when you *need* to make something 'transparent' and 'idiot-proof', that's for the API that's seen by the external clients/users of the class (not so much for the implementor of the class).
ChrisW
you will need to overload operator. (not possible) to really answer the OP's question though. your idea and my implementation are just workarounds, that do not really fit any real world use i think (to easy to miss using operator->)
Johannes Schaub - litb
ChrisW
"your idea and my implementation are just workarounds" ... well and apparently the OP was just idle curiosity; but it was fun to be able to answer 'yes' (it was like, "never say 'never'"): you *can* do some pretty baroque things with C++.
ChrisW
+13  A: 

Yes-ish, with a bit of extra code, some indirection and another class and using the -> instead of the . operator.

// The class for which calling any method should call PreMethod first.
class DogImplementation
{
public:
   void PreMethod();
   void Bark();
private:
   DogImplementation(); // constructor private so can only be created via smart-pointer.
   friend class Dog; // can access constructor.
};

// A 'smart-pointer' that wraps a DogImplementation to give you
// more control.
class Dog
{
public:
   DogImplementation* operator -> ()
   {
       _impl.PreMethod();
       return &_impl;
   }
private:
   DogImplementation _impl;
};

// Example usage of the smart pointer. Use -> instead of .
void UseDog()
{
  Dog dog;
  dog->Bark();    // will call DogImplementation::PreMethod, then DogImplementation::Bark
}

Well.. something roughly along those lines could be developed into a solution that I think would allow you to do what you want. What I've sketched out there probably won't compile, but is just to give you a starting point.

Scott Langham
i think your solution has the advantage of not accidentally using the dot to call functions. so u get +1 by me too ;) have fun
Johannes Schaub - litb
A: 

I'm not sure exactly what your restrictions are, so I don't know if this helps. If your object a singleton, you could stick all the code that gets called for every function call in the call to get the singleton.

Downside is all your other functions calls get ugly. And you may not be able to make the object a singleton.

+1  A: 

If I'm not mistaken this is a feature of what is called Aspect Oriented Programming.

Ulrich Gerhardt
+4  A: 

You can derive from this class template:

namespace detail {
struct const_tag;
struct nonconst_tag;

/* T is incomplete yet when pre_call is instantiated. 
 * so delay lookup of ::impl until call to operator-> 
 * happened and this delay_lookup is instantiated */
template<typename U, typename>
struct delay_lookup; 

template<typename U>
struct delay_lookup<U, nonconst_tag>
{
    typedef typename U::template get_impl<
        typename U::derived_type>::type impl_type;
    impl_type* u;
    delay_lookup(impl_type* u):u(u) { }
    impl_type* operator->() { return u; }
};

template<typename U>
struct delay_lookup<U, const_tag> {
    typedef typename U::template get_impl<
        typename U::derived_type>::type const impl_type;
    impl_type* u;
    delay_lookup(impl_type* u):u(u) { }
    impl_type* operator->() { return u; }
};

} // detail::

template<typename T>
struct pre_call {
private:
    friend class detail::delay_lookup<pre_call, detail::const_tag>;
    friend class detail::delay_lookup<pre_call, detail::nonconst_tag>;
    typedef T derived_type;

    /* pre_call is the friend of T, and only it
     * is allowed to access T::impl */
    template<typename U> struct get_impl {
        typedef typename U::impl type;
    };

protected:
    typedef boost::function<void(T const&)> fun_type;
    fun_type pre;

    template<typename Fun>
    pre_call(Fun pre):pre(pre) { }

public:
    /* two operator->: one for const and one for nonconst objects */
    detail::delay_lookup<pre_call, detail::nonconst_tag> operator->() { 
        pre(*get_derived()); 
        return detail::delay_lookup<pre_call, 
            detail::nonconst_tag>(&get_derived()->d);
    }

    detail::delay_lookup<pre_call, detail::const_tag> operator->() const { 
        pre(*get_derived()); 
        return detail::delay_lookup<pre_call, 
            detail::const_tag>(&get_derived()->d);
    }

private:
    T * get_derived() { 
        return static_cast<T *>(this); 
    }

    T const* get_derived() const { 
        return static_cast<T const*>(this); 
    }
};

And use it like this:

struct foo : pre_call<foo> {
private:
    /* stuff can be defined inline within the class */
    struct impl { 
        void some() const {
            std::cout << "some!" << std::endl;
        }

        void stuff()  {
            std::cout << "stuff!" << std::endl;
        }
    };

    void pre() const { 
        std::cout << "pre!" << std::endl;
    }

    friend struct pre_call<foo>;
    impl d;

public:
    foo():pre_call<foo>(&foo::pre) { }    
};

int main() {
    foo f;
    f->some();
    f->stuff();
    // f.some(); // forbidden now!
}

Previously i had a version that called post functions too. But i dropped it. It would have needed additional work. However, i would still not recommend you to do this "call function automatically" thingy. Because one can easily forget to use the operator-> syntax and just use the dot - and suddenly have the pre function not called

Update: The version above takes care of that, so one cannot accidentally call functions with the dot anymore.

Johannes Schaub - litb
hmm why should i make some private? it's a public method of foo. i don't understand what you mean
Johannes Schaub - litb
I think there are ways to avoid accidentally using the dot operator. You couldn't accidentally use it with a solution something along the lines of the one I've given. +1 templating would allow better reuse with less typing.
Scott Langham
Oh right - never mind - I was thinking that by making some() private that you'd prevent the . usage, but it would prevent both usages.
Eclipse
solved the thing :)
Johannes Schaub - litb