4

I suppose most of the persons on this site will agree that implementation can be outsourced in two ways:

  • private inheritance
  • composition

Inheritance is most often abused. Notably, public inheritance is often used when another form or inheritance could have been better and in general one should use composition rather than private inheritance.

Of course the usual caveats apply, but I can't think of any time where I really needed inheritance for an implementation problem.

For the Boost Parameter library however, you will notice than they have chosen inheritance over composition for the implementation of the named parameter idiom (for the constructor).

I can only think of the classical EBO (Empty Base Optimization) explanation since there is no virtual methods at play here that I can see.

Does anyone knows better or can redirect me to the discussion ?

Thanks, Matthieu.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722

2 Answers2

2

EDIT: Ooopss! I posted the answer below because I misread your post. I thought you said the Boost library used composition over inheritance, not the other way around. Still, if its usefull for anyone... (See EDIT2 for what I think could be the answer for you question.)

I don't know the specific answer for the Boost Parameter Library. However, I can say that this is usually a better choice. The reason is because whenever you have the option to implement a relationship in more than one way, you should choose the weakest one (low coupling/high cohesion). Since inheritance is stronger than composition...

Notice that sometimes using private inhertiance can make it harder to implement exception-safe code too. Take operator==, for example. Using composition you can create a temporary and do the assignment with commit/rollback logic (assuming a correct construction of the object). But if you use inheritance, you'll probably do something like Base::operator==(obj) inside the operator== of the derived class. If that Base::operator==(obj) call throws, you risk your guarantees.

EDIT 2: Now, trying to answer what you really asked. This is what I could understand from the link you provided. Since I don't know all details of the library, please correct me if I'm wrong.

When you use composition for "implemented in terms of" you need one level of indirection for the delegation.


struct AImpl 
{ 
  //Dummy code, just for the example.
  int get_int() const { return 10; }
};

struct A { AImpl * impl_; int get_int() const { return impl->get_int(); } /* ... */ };

In the case of the parameter-enabled constructor, you need to create an implementation class but you should still be able to use the "wrapper" class in a transparent way. This means that in the example from the link you mentioned, it's desired that you can manipulate myclass just like you would manipulate myclass_impl. This can only be done via inheritance. (Notice that in the example the inheritance is public, since it's the default for struct.)

I assume myclass_impl is supposed to be the "real" class, the one with the data, behavior, etc. Then, if you had a method like get_int() in it and if you didn't use inheritance you would be forced to write a get_int() wrapper in myclass just like I did above.

Leandro T. C. Melo
  • 3,974
  • 22
  • 22
  • I get your point with the 'delegation' problem, however we are specifically speaking of a delegation of 'Constructors' here, which are tricky beasts since on the contrary to others languages (such as Python), constructors are not inherited. Also, as far as I know, the macro they use (BOOST_PARAMETER_CONSTRUCTOR), will actually take care of all the boiler-plate code. – Matthieu M. Sep 29 '09 at 06:42
  • @Matthieu - I see. Still I think the reason could be the same. Notice that inheriting constructors and delegating constructors are related but different things (both are in C++0x). You need one constructor that performs the "real" stuff. This is the one in myclass_impl. Since it's not the one the user is supposed to call, you need somehow another class with actual named constructors. I believe the macro BOOST_PARAMETER_CONSTRUCTOR could surely be written to use composition in myclass instead of inheritance. But would lead to the delegation issues I mentioned. – Leandro T. C. Melo Sep 29 '09 at 11:52
  • I understand what you mean. I had in fact just assumed the contrary: ie for me the only purpose of AImpl was to allow the use of the Boost.Parameters. However it makes perfect sense that for using this library you would rather add a wrapper around an already existing than modifying your class. It is also much easier this way to wrap existing classes... with the usual caveat that they had better been written to be used as base class. – Matthieu M. Sep 29 '09 at 18:55
0

This isn't a library I've ever used, so a glance through the documentation you linked to is the only thing I'm basing this answer on. It's entirely possible I'm about to be wrong, but...

They mention constructor delegation as a reason for using a common base class. You're right that composition could address that particular issue just as well. Putting it all in a single type, however, would not work. They want to boil multiple constructor signatures into a single user-written initialization function, and without constructor delegation that requires a second data type. My suspicion is that much of the library had already been written from the point of view of putting everything into the class itself. When they ran into the constructor delegation issue they compromised. Putting it into a base class was probably closer to what they were doing with the previous functionality, where they knew that both interface and implementation aspects of the functionality would be accessible to the class you're working with.

I'm not slamming the library in any way. I highly doubt I could put together a library like this one in any reasonable amount of time. I'm just reading between the lines. You know, speaking from ignorance but pretending I actually know something. :-)

Darryl
  • 5,907
  • 1
  • 25
  • 36
  • I actually saw that they mention this is the 'usual' workaround around the missing feature of 'delegating constructors'. I however still fail to see why this should be addressed by Inheritance rather than Composition. Itcmelo above mentioned that this is public inheritance, but I am inclined to think this is an artifact of the example, struct being easier to write than class + public. – Matthieu M. Sep 29 '09 at 06:47
  • After thinking about it, I prefer inheritance in this case. In memory and execution the two approaches are almost identical. The difference is primarily in syntax. As itcmelo mentioned yesterday, composition requires an extra syntactic level of indirection, such as "a.x" instead of just "x". Inheritance allows you to continue to use just "x". Since this is a workaround, a hack, is it better to use a workaround that requires you to change code throughout the entire class, or one that allows you to write most of your code in the same form you would have used if the hack had not been necessary? – Darryl Oct 01 '09 at 04:28