6.05 Object Composition (HAS-A), Destructor Chains & Deterministic Hardware Teardown
Executive Summary: Building composite objects through composition (HAS-A relationships). We examine constructor and destructor execution chains, and demonstrate how composite RAII classes automatically power down peripherals in reverse order of initialization upon scope exit.
💻 1. Annotated Source Code
#include <iostream> #include "IceCreamSundae.h" using namespace std; int main() { IceCreamSundae basicVanilla("Vanilla"); basicVanilla.printSundae(); IceCreamSundae deluxeChocolate("Chocolate"); deluxeChocolate.addTopping("Whipped Cream"); deluxeChocolate.addTopping("Sprinkles"); deluxeChocolate.addTopping("Cherries"); cout << endl; deluxeChocolate.printSundae(); return 0; }
#ifndef ICE_CREAM_SUNDAE_H #define ICE_CREAM_SUNDAE_H #include <string> #include <vector> using namespace std; class IceCreamSundae { public: IceCreamSundae(string flavor); void addTopping(string topping); string getFlavor() const; vector<string> getToppings() const; void printSundae() const; private: string flavor; vector<string> toppings; }; #endif
#include "IceCreamSundae.h" #include <iostream> using namespace std; IceCreamSundae::IceCreamSundae(string flavor) { this->flavor = flavor; } void IceCreamSundae::addTopping(string topping) { toppings.push_back(topping); } string IceCreamSundae::getFlavor() const { return flavor; } vector<string> IceCreamSundae::getToppings() const { return toppings; } void IceCreamSundae::printSundae() const { cout << "Sundae flavor: " << flavor << endl; cout << "Toppings: " << endl; if (toppings.empty()) { cout << "None"; } else { for (string topping : toppings) { cout << topping << ", "; } } cout << endl; }
📐 2. Architecture & UML Class Model
<<class>>
IceCreamSundae
Aggregator
Attributes / Data Members
-numScoops : int32_t
-flavor : std::string
-toppings : std::vector<std::string>
Operations / Methods
+IceCreamSundae(flavor: string, numScoops: int)
+addTopping(topping: string) : void
+printSundae() : void const
+getFlavor() : std::string const
+getNumScoops() : int32_t const
📚 3. Core C++ Concepts Deep-Dive
1. Object Composition (HAS-A)
Composition embeds one class instance inside another as a member variable. The composite object controls the lifetime of its member sub-objects.
2. Constructor & Destructor Execution Order
- Construction: Member objects are constructed first (in declaration order), followed by the enclosing class constructor body.
- Destruction: The enclosing class destructor executes first, followed by member destructors in reverse order of declaration.
⚡ 4. Embedded Systems & Hardware Reality
1. Safe Hardware Peripheral Teardown Chains
In power-sensitive embedded systems, RAII composite drivers leverage reverse-order destruction to power down sub-peripherals in strictly safe sequences (e.g. disabling DMA $\rightarrow$ disabling SPI $\rightarrow$ gating peripheral clock).
💡 5. Production-Ready Embedded Refactoring
RAII composite sensor subsystem with automatic hardware teardown:
💡 Production-Ready Refactor
#include <cstdint> struct SpiClockGate { SpiClockGate() noexcept { /* RCC->APB2ENR |= SPI1_EN; */ } ~SpiClockGate() noexcept { /* RCC->APB2ENR &= ~SPI1_EN; Disable clock on exit! */ } }; struct GpioChipSelect { GpioChipSelect() noexcept { /* Set CS Pin LOW (Active) */ } ~GpioChipSelect() noexcept { /* Set CS Pin HIGH (Idle) */ } }; class SpiTransactionScope { private: SpiClockGate clock_gate_; // Constructed 1st; Destroyed 2nd GpioChipSelect chip_select_; // Constructed 2nd; Destroyed 1st public: void write_data(uint8_t byte) noexcept { /* SPI1->DR = byte; */ } };
📝 Knowledge Verification Quiz
Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.
Q1. In what order are member sub-objects destroyed when an enclosing class instance goes out of scope?
Detailed Explanation:
C++ guarantees that destructors are invoked in reverse order of member declaration, ensuring proper symmetric teardown of dependent resources.
Q2. What relationship does 'composition' represent in Object-Oriented Design?
Detailed Explanation:
Composition represents a 'HAS-A' relationship (e.g., a Car HAS-A Engine), where the outer class owns and manages the lifecycle of the inner component.
Q3. How does RAII (Resource Acquisition Is Initialization) prevent peripheral power drain in battery devices?
Detailed Explanation:
RAII ties hardware peripheral power states to object lifetimes, guaranteeing that peripherals are safely disabled as soon as their enclosing scope exits.
Q4. If class A contains member class B, when is B's constructor executed relative to A's constructor body?
Detailed Explanation:
All member sub-objects are fully constructed before the body of the enclosing class constructor starts execution.