- References
- Function Overloading
- Default Function Arguments
- Inline Function
- Dynamic Memory Allocation
- Placement New
- nullptr
- Namespaces
- Type Aliases
- Enum classes
- constexpr
- static_assert
- mutable Keyword
- auto Keyword
- Smart Pointers
- Basics of Classes
- Constructors
- Destructors
- Operator Overloading
- Copy Semantics
- Move Semantics
- Composition, RAII & Ownership
- Inheritance
- Polymorphism
- Abstraction
- Encapsulation
- Template
- Static Memory
- Friend Function
- this Pointer
- Function Pointer
- Lambdas and Callback Management
- Union
Inheritance (Code Reusability)

Inheritance is a mechanism where a new class (Derived Class) acquires the properties and behaviors (variables and functions) of an existing class (Base Class).
It enables the "Is-a" Relationship (e.g., a Button is a GPIO_Device).
This allows you to write generic code in a Base class (like Packet) and extend or specialize it in Derived classes (like WiFiPacket, BluetoothPacket) without rewriting the common logic.
Syntax & Usage
1. Basic Declaration
Use the : symbol followed by the access mode (usually public).
// Base Class (Parent)
class SerialPort {
public:
void open(int baud) { /* Generic open logic */ }
void close() { /* Generic close logic */ }
};
// Derived Class (Child)
// Syntax: class Child : access_specifier Parent
class UART : public SerialPort {
public:
// UART inherits open() and close() automatically.
// Adds new specific functionality
void set_parity(int p) { /* ... */ }
};
UART u;
u.open(9600); // Calls Base function
u.set_parity(1); // Calls Derived function2. Access Specifiers (protected)
Inheritance introduces a new access level: protected.
private: Visible only to the Base class. (Derived classes cannot see it).protected: Visible to the Base class and Derived classes. (Outsiders cannot see it).public: Visible to everyone.
class Sensor {
protected:
int raw_adc_value; // Children can access this directly
private:
int secret_key; // Children CANNOT access this
};
class TempSensor : public Sensor {
public:
void read() {
raw_adc_value = HW_Read(); // ✅ Allowed (protected)
// secret_key = 0; // ❌ Error (private)
}
};3. Constructor Execution Order
When you create a Derived object, the Base constructor runs first, then the Derived constructor.
When destroyed, the order is reversed (Derived destructor first, then Base).
class Base {
public:
Base(int x) { /* Init Base */ }
};
class Derived : public Base {
public:
// Must explicit call Base constructor in initializer list
Derived(int x, int y) : Base(x) {
/* Init Derived */
}
};Memory Layout
A Derived class object is essentially the Base class object with the new fields "glued" to the end of it. It forms a single contiguous block of memory.
| Address Offset | Content | Belongs To |
|---|---|---|
0x00 | Base::var1 | Base Class |
0x04 | Base::var2 | Base Class |
0x08 | Derived::new_var | Derived Class |
Relevance in Embedded/Firmware
1. Hardware Abstraction (HAL)
This is the standard architecture for portable drivers.
- Base Class:
Display(Defines genericdrawPixel,drawRect,clear). - Derived Class:
ILI9341_Display(ImplementsdrawPixelfor specific hardware). - Application: Writes to
Display*. It doesn't care which screen is connected.
2. Generic Protocol Handling
If you have multiple communication packets (Command Packet, Data Packet, Ack Packet) that all share a Header (ID, Length) and CRC, you create a BasePacket class.
BasePackethandles CRC calculation and Header parsing.- DataPacket adds the payload buffer. This saves Flash memory by not duplicating the CRC logic 3 times.
Common Pitfalls (Practical Tips)
| Pitfall | Details |
|---|---|
| ❌ Object Slicing | If you assign a Derived object to a Base variable (Base b = derived;), the derived parts are sliced off. Always use Pointers (Base*) or References (Base&) when dealing with hierarchy. |
| ❌ Missing Virtual Destructor | If you delete a Derived object via a Base pointer (Base* b = new Derived(); delete b;), the Derived destructor will NOT run unless the Base destructor is marked virtual. This causes memory leaks. |
| ❌ Multiple Inheritance | Inheriting from two classes (class C : public A, public B) is possible but dangerous (ambiguity, diamond problem). Avoid it in firmware; use Composition instead. |
| ✅ Composition over Inheritance | If a class "Has a" dependency (e.g., A Car has an Engine), use a member variable, not inheritance. Only use Inheritance for "Is a" relationships (e.g., A Car is a Vehicle). |
Concept understood? Let's apply and learn for real