Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement class composition in C++?

Tags:

c++

oop

If I understand correctly we have at least two different ways of implementing composition. (The case of implementation with smart pointers is excluded for simplicity. I almost don't use STL and have no desire to learn it.)

Let's have a look at Wikipedia example:

class Car
{
  private:
    Carburetor* itsCarb;
  public:   
    Car() {itsCarb=new Carburetor();}
    virtual ~Car() {delete itsCarb;}
};

So, it's one way - we have a pointer to object as private member. One can rewrite it to look like this:

class Car
{
  private:
    Carburetor itsCarb;
};

In that case we have an object itself as private member. (By the way, am I right to call this entity an object from the terminology point of view?)

In the second case it is not obligatory to implicitly call default constructor (if one need to call non-default constructor it's possible to do it in initializer list) and destructor. But it's not a big problem...

And of course in some aspects these two cases differ more appreciably. For example it's forbidden to call non-const methods of Carburetor instance from const methods of Car class in the second case...

Are there any "rules" to decide which one to use? Am I missing something?

like image 348
Wildcat Avatar asked Dec 05 '09 23:12

Wildcat


People also ask

What is composition of a class?

An object can have references to objects of other classes. This is called composition or a has-a relationship. In UML, this might be modeled as an association, aggregration or "composition"* relationship, depending on how strong the relationship is.

What is CS composition?

Composition is one of the fundamental concepts in object-oriented programming. It describes a class that references one or more objects of other classes in instance variables. This allows you to model a has-a association between objects. You can find such relationships quite regularly in the real world.

What is composition in oops with example?

For example, A 'Human' class is a composition of Heart and lungs. When the human object dies, nobody parts exist. The composition is a restricted form of Aggregation. In Composition, one class includes another class and is dependent on it so that it cannot functionally exist without another class.


4 Answers

In that case we have an object itself as private member. (By the way, calling this entity as object am I write from the terminology point of view?)

Yes you can say "an object" or "an instance" of the class.

You can also talk about including the data member "by value" instead of "by pointer" (because "by pointer" and "by value" is the normal way to talk about passing parameters, therefore I expect people would understand those terms being applied to data members).

Is there any "rules" to decide which one to use? Am I missed something?

If the instance is shared by more than one container, then each container should include it by pointer instead of value; for example if an Employee has a Boss instance, include the Boss by pointer if several Employee instances share the same Boss.

If the lifetime of the data member isn't the same as the lifetime of the container, then include it by pointer: for example if the data member is instantiated after the container, or destroyed before the container, or destroyed-and-recreated during the lifetime of the container, or if it ever makes sense for the data member to be null.

Another time when you must including by pointer (or by reference) instead of by value is when the type of the data member is an abstract base class.

Another reason for including by pointer is that that might allow you to change the implementation of the data member without recompiling the container. For example, if Car and Carburetor were defined in two different DLLs, you might want to include Carburetor by pointer: because then you might be able to change the implementation of the Carburetor by installing a different Carburetor.dll, without rebuilding the Car.dll.

like image 94
ChrisW Avatar answered Sep 24 '22 01:09

ChrisW


I tend to prefer the first case because the second one requires you to #include Carburettor.h in Car.h. Since Carburettor is a private member you should not have to include its definition somewhere else than in the actual Car implementation code. The use of the Carburettor class is clearly an implementation detail and external objects that use your Car object should not have to worry about including other non mandatory dependencies. By using a pointer you just need to use a forward declaration of Carburettor in Car.h.

like image 20
nico Avatar answered Sep 22 '22 01:09

nico


Composition: prefer member when possible. Use a pointer when polymorphism is needed or when a forward declaration is used. Of course, without smart pointer, manual memory management is needed when using pointers.

like image 37
stefaanv Avatar answered Sep 22 '22 01:09

stefaanv


If Carb has the same lifetime as Car, then the non-pointer form is better, in my opinion. If you have to replace the Carb in Car, then I'd opt for the pointer version.

like image 43
Richard Pennington Avatar answered Sep 21 '22 01:09

Richard Pennington