C++
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C++
-
Section 4: Memory Management
-
Section 5: Templates and Generic Programming
-
Section 6: The Standard Template Library
-
Section 7: Modern C++ Features
-
Section 8: Error Handling
-
Section 9: Multithreading
-
Section 10: Operator Overloading and Type Conversion
-
Section 11: Advanced Topics
-
Section 12: Tooling and Build Systems
-
Section 13: Design Patterns in C++
-
Section 14: Interfacing with C and Systems Programming
-
Section 15: Networking and IPC Basics
-
Section 16: Graphics and Game Programming Basics
-
Section 17: The Boost Libraries
-
Section 18: Data Structures and Algorithms in C++
-
Section 19: Practical Projects
-
Section 20: More Concurrency Patterns
-
Section 21: More OOP and Design Practice
-
Section 22: File I/O and Streams
-
Section 23: More Standard Library
-
Section 24: Practice Exercises
-
Section 25: Interview and Algorithm Practice
-
Section 26: Compiler and Language Internals
-
Section 27: GUI and Application Frameworks Overview
-
Section 28: Testing and Quality Practices
-
Section 29: Numerics Library
-
Section 30: Concepts Library (C++20)
-
Section 31: Ranges Library (C++20) In Depth
-
Section 32: More Utility Library
35: Operator Overloading: Arithmetic Operators
I've seen this happen a dozen times with developers moving from Python or JavaScript to C++. You build a class to represent a concept—like a 2D coordinate or a currency value—and then you try to use it naturally in a mathematical expression. It feels like it should just work, but then the compiler hits you with a wall of errors.
struct Vector2D {
float x, y;
};
int main() {
Vector2D pos1 = {10.0f, 5.0f};
Vector2D pos2 = {2.0f, 3.0f};
// This line triggers a massive compiler error
Vector2D result = pos1 + pos2;
return 0;
}
Why the compiler doesn't know how to add Vectors
The error you'll see usually says something like no match for 'operator+'. To the C++ compiler, Vector2D is just a chunk of memory containing two floats. It has no idea that "adding" two vectors means adding the x values together and the y values together. It doesn't assume you want a component-wise addition because, in some contexts, "adding" two objects might mean merging lists or appending strings.
You could fix this by writing a function like Vector2D add(Vector2D a, Vector2D b), but that makes your code clunky. Writing pos1 + pos2 is far more readable than add(pos1, pos2), especially when you start chaining operations together. This is where operator overloading comes in.
Teaching C++ the addition rule
To fix this, we define a special function called operator+. When the compiler sees the + symbol between two Vector2D objects, it will look for this function and call it instead.
struct Vector2D {
float x, y;
// We overload the + operator
Vector2D operator+(const Vector2D& other) const {
return {x + other.x, y + other.y};
}
};
Notice a few critical things here. First, I'm returning a new Vector2D. A common mistake I see is developers trying to modify the current object inside operator+. Don't do that. In mathematics, a + b = c doesn't change a or b. If you want to modify the object, that's what operator+= is for (which we'll hit later).
Second, I used const Vector2D& other. We pass by reference to avoid copying the object unnecessarily, and we mark it const because adding two vectors shouldn't change the values of the vectors being added. Finally, the const at the end of the function signature tells C++ that this method doesn't modify the object it's called on.
Handling scalar multiplication
Arithmetic isn't just about adding two identical types. Often, you'll want to multiply a vector by a number (a scalar) to scale it. This requires a slightly different approach because the left-hand side of the operation is a float, not a Vector2D.
If we put the operator inside the class, the left-hand side must be a Vector2D. To allow float * Vector2D, we define the operator as a non-member function:
struct Vector2D {
float x, y;
Vector2D operator+(const Vector2D& other) const {
return {x + other.x, y + other.y};
}
};
// Non-member function for scalar multiplication
Vector2D operator*(float scalar, const Vector2D& vec) {
return {vec.x * scalar, vec.y * scalar};
}
// Now this works:
Vector2D pos = {1.0f, 2.0f};
Vector2D scaled = 2.0f * pos;
I personally prefer keeping arithmetic operators as simple as possible. If the logic inside your operator+ starts getting complex (like involving database calls or heavy logging), you're probably overloading the operator when you should have just written a named function. Use overloading for things that mathematically feel like the operator they are replacing.
📋 Practical Task
Implementation: Complex Number Arithmetic Library
In mathematics, complex numbers consist of a real part and an imaginary part. Adding two complex numbers involves adding their real parts together and their imaginary parts together. Subtracting follows the same logic.
Your Task: Create a class ComplexNumber that allows for natural arithmetic. Implement the following:
- Two private member variables:
double realanddouble imag. - A constructor to initialize these values.
- An overloaded
operator+to return the sum of twoComplexNumberobjects. - An overloaded
operator-to return the difference between twoComplexNumberobjects. - A method
display()` that prints the number in the formata + bi.
Test Case: If you add (3.0, 2.0) and (1.0, 7.0), the result should be (4.0, 9.0). If you subtract the latter from the former, the result should be (2.0, -5.0).
There are no comments for now.