pattern support for traversing inheritance chain
Hi all - I have a case where I have a largeish inheritance hierarchy. I will be calling an initialization function on all objects before using them in some fashion. Basically what I need to happen is when I call init() on a Foo the following would occur: void Foo::init() { super::init(); // now with the knowledge that anything I inherited is set up, I can set myself up... } It is not necessary for every call to implement init, in which case the behavior should be that the call is propagated up the inheritance chain (which it is by default in C++). In order to make this work, I need to write different code for "super" in every class implementation, which is a bit error prone. Even if I don't copy/paste, my brain might be on autopilot and type something further up the inheritance chain than it should be. Alternatively, I could require that each class provides a typedef for super, but I'm still relying on myself to remember to call super's init function. Is there anything in boost that would support this kind of hierarchy traversal (semi-)automatically? If there is not, are there suggestions for ways to implement this in a less error-prone fashion? Thanks, Brian
2012/11/8 Brian Budge <brian.budge@gmail.com>
Hi all -
I have a case where I have a largeish inheritance hierarchy. I will be calling an initialization function on all objects before using them in some fashion.
Basically what I need to happen is when I call init() on a Foo the following would occur:
void Foo::init() { super::init(); // now with the knowledge that anything I inherited is set up, I can set myself up... }
It is not necessary for every call to implement init, in which case the behavior should be that the call is propagated up the inheritance chain (which it is by default in C++).
In order to make this work, I need to write different code for "super" in every class implementation, which is a bit error prone. Even if I don't copy/paste, my brain might be on autopilot and type something further up the inheritance chain than it should be. Alternatively, I could require that each class provides a typedef for super, but I'm still relying on myself to remember to call super's init function.
Is there anything in boost that would support this kind of hierarchy traversal (semi-)automatically? If there is not, are there suggestions for ways to implement this in a less error-prone fashion?
Thanks, Brian
I think the constructors in C++ work the way you want init() to work. You probably use two-step initialization, don't you? Can you avoid it? Regards, Kris
Thanks for the remark Kris. I had thought of that, but unfortunately, the two-step approach is necessary since I'm using a handle-to-data approach. The actual pointers (objects) associated with the handles may change, and the (possibly incremental) init needs to be re-run for the object. Brian On Wed, Nov 7, 2012 at 3:17 PM, Krzysztof Czainski <1czajnik@gmail.com>wrote:
2012/11/8 Brian Budge <brian.budge@gmail.com>
Hi all -
I have a case where I have a largeish inheritance hierarchy. I will be calling an initialization function on all objects before using them in some fashion.
Basically what I need to happen is when I call init() on a Foo the following would occur:
void Foo::init() { super::init(); // now with the knowledge that anything I inherited is set up, I can set myself up... }
It is not necessary for every call to implement init, in which case the behavior should be that the call is propagated up the inheritance chain (which it is by default in C++).
In order to make this work, I need to write different code for "super" in every class implementation, which is a bit error prone. Even if I don't copy/paste, my brain might be on autopilot and type something further up the inheritance chain than it should be. Alternatively, I could require that each class provides a typedef for super, but I'm still relying on myself to remember to call super's init function.
Is there anything in boost that would support this kind of hierarchy traversal (semi-)automatically? If there is not, are there suggestions for ways to implement this in a less error-prone fashion?
Thanks, Brian
I think the constructors in C++ work the way you want init() to work. You probably use two-step initialization, don't you? Can you avoid it?
Regards, Kris
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Hi Brian, On Wed, Nov 7, 2012 at 4:04 PM, Brian Budge <brian.budge@gmail.com> wrote:
Hi all -
I have a case where I have a largeish inheritance hierarchy. I will be calling an initialization function on all objects before using them in some fashion.
Basically what I need to happen is when I call init() on a Foo the following would occur:
void Foo::init() { super::init(); // now with the knowledge that anything I inherited is set up, I can set myself up... }
When I'm dealing with a situation like you describe (not using constructors), I find that Boost.Signals (or Signals2) do what I'm looking for.
I generally do something like the following: class B { typedef boost::signal<void()> OnInitListener; OnInitListener onInit_; public: boost::signals::connection connectOnInitListener(OnInitListener::slot_function_type cb) { return onInit_.connect(cb); } void onInit() { onInit_(); } }; class D : public B { D() { connectOnInitListener(bind(&D::onInitImpl, this)); } // Register our onInit handler. }; //Repeat for further derivatives. This means I don't need to state whom I inherit from, the order of calling is determined by the order of construction, and if one method doesn't need to listen for the onInit signal, everything works as expected. HTH, Nate
On Wed, Nov 7, 2012 at 3:21 PM, Nathan Crookston <nathan.crookston@gmail.com
wrote:
Hi Brian,
On Wed, Nov 7, 2012 at 4:04 PM, Brian Budge <brian.budge@gmail.com> wrote:
Hi all -
I have a case where I have a largeish inheritance hierarchy. I will be calling an initialization function on all objects before using them in some fashion.
Basically what I need to happen is when I call init() on a Foo the following would occur:
void Foo::init() { super::init(); // now with the knowledge that anything I inherited is set up, I can set myself up... }
When I'm dealing with a situation like you describe (not using constructors), I find that Boost.Signals (or Signals2) do what I'm looking for.
I generally do something like the following:
class B { typedef boost::signal<void()> OnInitListener; OnInitListener onInit_; public: boost::signals::connection connectOnInitListener(OnInitListener::slot_function_type cb) { return onInit_.connect(cb); }
void onInit() { onInit_(); } };
class D : public B { D() { connectOnInitListener(bind(&D::onInitImpl, this)); } // Register our onInit handler. };
//Repeat for further derivatives.
This means I don't need to state whom I inherit from, the order of calling is determined by the order of construction, and if one method doesn't need to listen for the onInit signal, everything works as expected.
HTH, Nate
Hi Nate - Yes, this seems quite useful. With signal connect, I guess it's more-or-less pushing-back on a list of function objects? When the signal is called, it iterates the list and calls each function object? Thanks for the suggestion. Seems like a good way to go. Brian
Hi Brain, On Wed, Nov 7, 2012 at 4:32 PM, Brian Budge <brian.budge@gmail.com> wrote:
Yes, this seems quite useful. With signal connect, I guess it's more-or-less pushing-back on a list of function objects? When the signal is called, it iterates the list and calls each function object?
Yes, this is the default behavior. The library is much more sophisticated than just that -- you can play with call order, combining return types and more. I first used it to do pretty much what you described, however -- it's eliminated the class of 'called wrong base function' and 'forgot to call base function/ errors. Nate
participants (3)
-
Brian Budge
-
Krzysztof Czainski
-
Nathan Crookston