Let's say we have two classes, A
and B
. When using composition to model a "has-a" or "is-implemented-in-terms-of" relationship (e.g. B
has-a A
), one of the drawbacks vs. inheritance is that B
does not the contain public functionality of A
that it requires. In order to gain access to A
s public functions, it is necessary to provide forwarding functions (as opposed to inheritance, where B
would inherit all of A
s public functions).
To give a more concrete example, let's say we have a Person
which has-a ContactInfo
:
using namespace std;
class ContactInfo
{
public:
ContactInfo();
void updateAddress(string address);
void updatePhone(string phone);
void updateEmail(string email);
private:
string address;
string phone;
string email;
};
class Person
{
public:
Person();
// Forwarding functions:
void updateAddress(string address){contactInfo.updateAddress(address)};
void updatePhone(string phone){contactInfo.updatePhone(phone)};
void updateEmail(string email){contactInfo.updateEmail(email)};
private:
ContactInfo contactInfo;
};
Ignoring any deficiencies in the design (it is just a contrived example to demonstrate my question below), I have had to tediously replicate the exact function signatures from ContactInfo
in Person
. In a more complex example there could be many such functions, and many layers of composed classes, leading to much code duplication with all the usual problems of maintenance and being error-prone, etc.
Nonetheless, this is the recommended practice for modelling "has-a" or "is-implemented-in-terms-of" according to sources such as Item 38 of Meyers' Effective C++, and Item 24 of Sutter's Exceptional C++ (link).
Whilst researching this, I came across this Wikipedia article which discusses the same topic. At the bottom of the article, it suggests the following:
One drawback to using composition in place of inheritance is that all of the methods being provided by the composed classes must be implemented in the derived class, even if they are only forwarding methods. [...] This drawback can be avoided by using traits.
I am fairly new to the concept of traits and with everything I have read, I am finding it hard to relate to the above statement. My question therefore is: How would one go about using traits to avoid forwarding functions with composition? An answer based on my example (Person
and ContactInfo
) would be ideal.
EDIT: Just to clarify, in response to some of the answers, I am aware of private inheritance as an alternative to composition for modelling "is-implemented-in-terms-of". My question is not about that, it is specifically about the meaning of Wikipedia's statement relating to traits. I am not asking for alternatives to composition. I've bolded my question to make it clearer that this is what I'm asking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With