S R T B H P N

Compound Objects

Synopsis:

The C++ language was built from the ground up to support user defined value types. It does that with copy constructors and copy assignment operators that allow the designer to implement deep copies. That makes the state of the destination object have the same value as the state of the source, but those states are independent. If the source changes its state later, that does not affect the state of the destination.

C++ provides destructors that are called when the thread of execution leaves the scope where the instance was declared. This means the developers have tight control over how and when an instance's resources are returned to the process, for use by other instances. More importantly, the users of C++ classes do not need to be aware of these resource allocations and deallocations. They simply use instances of the classes and the instances take care of all resource management.

The language also provides move construction and move assignment operations. Move construction builds an instance, taking ownership of another instance's state. This transfer is very efficient, usually effected with a pointer swap. Similarly, move assignment discards the destination's state and it takes ownership of the source's state.

Move operations usually only occur when the source is a temporary object, but the compiler can be coerced to execute a move on a non-temporary object by using the std::move(...) operation. Note that you need to be careful with this, as the source no longer owns it's former state and may be unable to continue. Essentially, the use of the std::move(...) is a promise not to use the source object any longer, or to reinitialize it in some effective way.

There are four class relationships, doc, we use to construct Object Oriented Designs: Inheritance, Composition, Aggregation, and Using. Inheritance is an "is-a" relationship. Composition is a strong ownership or "part-of" relationship. Aggregation is also a "part-of" relationship, but is weaker than composition because it does not guarantee that the aggregated part is owned, only that it can be owned by the aggregator. Finally, using is a dependency on an object that is not part of the user, was not created by the user, and should not be destroyed by the user.

Compound Object Example:

Construction Behaviors:

  1. An instance of C is always contained within the footprint of each instance of B.
  2. Clients of B do not see C's public interface. That is only accessible to B.
  3. Similarly, an instance of B is always contained within each instance of D.
  4. Since D derives from B via public inheritance, its public methods become public methods of D.
  5. The C++ language guarantees that a constructor call is made for the creation of every object even if the class designer did not provide constructors. It does that by generating default and copy constructors that do member-wise construction of the class's bases and data elements if the class definition does not explicitly provide them.
  6. Similarly, the language guarantees that a destructor call is made for every object as it leaves the scope in which it was declared, even if the class designer did not provide a destructor. In that case the compiler generates a destructor that does member-wise destruction of each of the class's bases and member data.
  7. Note: This means that you must always decide whether to provide default and copy constructors and destructors for every class you design.
  8. If a class's bases and member data have correct copy, assignment, and destruction semantics, then you don't need to, and should not, provide them. That is always true if your class holds only primitive types and containers from the Standard Template Library, or holds instances of classes for which that is true.
  9. If your class holds pointers to data on the heap, then you must provide copy, assignment, and destruction operations, or qualify those operations with delete.
  10. If you class holds any types that do not support copying or assignment, like mutexes and critical sections, then you must qualify copy, assignment, and destruction operations with delete.

Example Code:

Compound Objects CodeSnap, Code Doc

This code has classes C, B, D, and U, shown in the diagram above. All of these classes, in the demo code, have correct copy,assignment, destruction, and move semantics. So we normally would not provide those operations, deferring to the compiler generated ones.
However, they are provided here so that they can write to the console to indicate to you how and when they are called.
CST strip