11.17 Creating Type-Safe Physical Units & Fixed-Point Math Wrappers
Executive Summary: Exploring operator overloading (
+, ==, <<). We show how embedded systems use operator overloading to build type-safe physical unit types (Volts, Amperes) and fixed-point math wrappers avoiding FPU overhead.
💻 1. Annotated Source Code
#ifndef RECTANGLE_H #define RECTANGLE_H class Rectangle { public: Rectangle(); Rectangle(double length, double width); double getLength() const; double getWidth() const; void setLength(double length); void setWidth(double width); double area() const; double perimeter() const; //overloaded operators bool operator==(const Rectangle& other) const; bool operator!=(const Rectangle& other) const; bool operator<(const Rectangle& other) const; Rectangle operator+(const Rectangle& other) const; void operator=(const Rectangle& other); private: double length; double width; }; #endif
#include "Rectangle.h" Rectangle::Rectangle() { length = 1; width = 1; } Rectangle::Rectangle(double length, double width) { this->length = length; this->width = width; } double Rectangle::getLength() const { return length; } double Rectangle::getWidth() const { return width; } void Rectangle::setLength(double length) { this->length = length; } void Rectangle::setWidth(double width) { this->width = width; } double Rectangle::area() const { return length * width; } double Rectangle::perimeter() const { return 2 * (length + width); } bool Rectangle::operator==(const Rectangle& other) const { return length == other.length && width == other.width; } bool Rectangle::operator!=(const Rectangle& other) const { return !(*this == other); } bool Rectangle::operator<(const Rectangle & other) const { return this->area() < other.area(); } Rectangle Rectangle::operator+(const Rectangle& other) const { return Rectangle(length + other.length, width + other.width); } void Rectangle::operator=(const Rectangle& other) { length = other.length; width = other.width; }
#include <iostream> #include "Rectangle.h" using namespace std; int main() { Rectangle rect1(10, 20); Rectangle rect2(50, 100); Rectangle rect3(10, 20); Rectangle resultRect; resultRect = rect1 + rect2; //rect1.operator+(rect2); cout << "rect1 == rect3? " << boolalpha << (rect1 == rect3) << endl; cout << "rect1 != rect2? " << boolalpha << (rect1 != rect2) << endl; cout << "resultRect: " << resultRect.getLength() << " * " << resultRect.getWidth() << " = " << resultRect.area() << endl; cout << "rect1 < rect2? " << boolalpha << (rect1 < rect2) << endl; return 0; }
📐 2. Architecture & UML Class Model
<<class>>
Rectangle
Overloaded Entity
Attributes / Data Members
-length : double
-width : double
Operations / Methods
+Rectangle(l: double, w: double)
+operator+(other: const Rectangle&) : Rectangle const
+operator==(other: const Rectangle&) : bool const
+operator!=(other: const Rectangle&) : bool const
+friend operator<<(os: ostream&, r: const Rectangle&) : ostream&
📚 3. Core C++ Concepts Deep-Dive
Operator Overloading Syntax
Custom classes can overload arithmetic and comparison operators to act like fundamental types.
⚡ 4. Embedded Systems & Hardware Reality
Fixed-Point Math for Cortex-M0/M3 (No FPU)
Microcontrollers without hardware Floating Point Units emulate floats in software, taking dozens of cycles. Overloading operators on fixed-point integer types enables fast arithmetic with clean mathematical syntax.
💡 5. Production-Ready Embedded Refactoring
💡 Production-Ready Refactor
struct Millivolts { int32_t val; constexpr Millivolts operator+(Millivolts o) const { return {val + o.val}; } constexpr bool operator==(Millivolts o) const { return val == o.val; } };
📝 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. Why is operator overloading beneficial for physical units in embedded systems?
Detailed Explanation:
Type-safe unit wrappers catch physical calculation mistakes at compile time with zero runtime overhead.