Subj : Re: Can you mimic atexit() for class functions? To : borland.public.cpp.borlandcpp From : gary Date : Mon Oct 13 2003 05:17 pm Benjamin: wow. didn't know my question would start a war... anyway, YOU hit the nail on the head by correctly noting that my "atexit" allusion was merely an example of a mechanism that allows user code to chain a series of functions together to be called at some future time, rather than a requirement for a function to be called at program exit (frankly, i would assume that if one really wanted an "atexit" look-alike, one would simply put their "clean up" code appropriate for each object in the destructor...which is what should be happening anyway). my own attempt at creating this "callback" chain was what i guess i would characterize as the somewhat brutish "C" version of your mechanism. that is, i avoided the flurry of improper cast errors that were generated when i tried the straightforward (for "C") pass-a-pointer-to-my-function version of an AddCallback() function by creating a CallbackList class that contained a virtual "void Callback()" member function, and then made all classes that were to utilize this mechanism inherit that CallbackList class. this allowed the interface to use a common CallbackList "this" pointer. however, i wasn't savvy enough to use the two-layer approach you did using a vector. i'm too new to "real" C++, so i just had my CallbackList class contain a "CallbackList *pNext" member as well, so that the constructor could automatically add the new "this" pointer to a linked-list of pNext's and the destructor could excise it from that list. the downside of my method (from my limited perspective, that is, as i didn't really recognize the "safety" issues) was that the callback functions in each object had to have the same name (e.g., "Callback()") since the "this" pointer was simply used to call the appropriate function by its fixed member function name. i note that this same limitation exists in your method, which replaces my "C" style linked-list mechanism with what i take to be a more "C++" style use of vectors. if the question is not too stupid, maybe you could give me reader's digest condensed version as to the benefit of using the two-class method you used? also, one reason i didn't like the naming limitation was the inability to re-use the same callback class for two different purposes; that is, for two different chains of callbacks, say, SomeArbitraryFunc1() and SomeArbitraryFunc2(). if i understand your method correctly, the best way i could do this would be to make the CallbackInterface class contain both a virtual Callback1() and Callback2() member function, and have DoCallbacks1() and DoCallbacks2() functions to call each list? alas, otherwise it does seem as if the one thing i wanted to avoid is unavoidable (the ability to chain arbitrary "void (*)()" callbacks the way one would in "C"). i guess that just violates the whole notion of "C++" objects, which really want to convey both the "verb" and the "subject" in the callback function name. (mixing grammar and OOP terms...) in "C", one would likely just use a callback with the form "void (*pfn)(void *amorphous_thing)" to allow the arbitrary action/verb "pfn" to operate on the arbitrary object/subject "amorphous_thing". thanks for not letting the "war" distract you from answering what you correctly understood to be the actual point of my original question. :gary Benjamin Pratt wrote: > This is a 'better' way to do the same thing in C++. You'll notice that there > is actually no function pointers at all. The previous example works, but is > not very safe. Following is the way I would recommend accomplishing your > callback container functionality: > > > #include > #include > > class CallbackInterface; > > class CallbackContainer { > public: > void AddCallback(CallbackInterface* pCallback) { > callbacks.push_back(pCallback); } > void DoCallbacks(); > > private: > typedef std::vector CALLBACKS; > CALLBACKS callbacks; > > } g_CallbackContainer; > > class CallbackInterface { > public: > CallbackInterface() { g_CallbackContainer.AddCallback(this); } > virtual void Callback() = 0; > }; > > class A : public CallbackInterface { > public: > A(int value) : _value(value) {} > > void Callback() { std::cout << "A::Callback() = " << _value << > std::endl; } > > private: > int _value; > }; > > class B : public CallbackInterface { > public: > B(float value) : _value(value) {} > > void Callback() { std::cout << "B::Callback() = " << _value << > std::endl; } > > private: > float _value; > }; > > void CallbackContainer::DoCallbacks() { > for(CALLBACKS::iterator p = callbacks.begin(); p != callbacks.end(); ++p) > (*p)->Callback(); > } > > int main(void) { > > A a1(1), a2(2), a3(3); > B b1(1.5), b2(2.5), b3(3.5); > > g_CallbackContainer.DoCallbacks(); > > return 0; > } > > > .