A journey through object-oriented programming in C++ β from the very first class to advanced STL algorithms.
- About
- Modules Overview
- CPP00 β Namespace Β· Classes Β· I/O
- CPP01 β Memory Β· References Β· Pointers
- CPP02 β Fixed-Point Β· Operator Overloading
- CPP03 β Inheritance
- CPP04 β Polymorphism Β· Abstract Classes
- CPP05 β Exceptions
- CPP06 β C++ Casts
- CPP07 β Templates
- CPP08 β Templated Containers Β· Iterators Β· Algorithms
- CPP09 β STL Containers
- How to Build & Run
- Author
The C++ Modules project at 42 School is a series of progressively challenging exercises designed to introduce the core concepts of Object-Oriented Programming in C++98. Starting from namespaces and simple classes, the journey culminates in sophisticated uses of the Standard Template Library, casts, templates, and sorting algorithms.
Each module lives in its own directory (cpp00/ through cpp09/), and every exercise within a module builds upon the last.
Key rules applied throughout:
- C++98 standard only (
-std=c++98) - No external libraries
- Orthodox Canonical Form (OCF) for all classes when required
- No memory leaks β proper
new/deletemanagement
| Module | Core Topics | Exercises |
|---|---|---|
| CPP00 | Namespaces, Classes, I/O, const, static |
ex00 Β· ex01 Β· ex02 |
| CPP01 | Heap vs Stack, Pointers, References, Switch | ex00 β ex06 |
| CPP02 | Fixed-point arithmetic, Operator Overloading, OCF | ex00 Β· ex01 Β· ex02 |
| CPP03 | Single Inheritance, Constructor chaining | ex00 Β· ex01 Β· ex02 |
| CPP04 | Virtual functions, Deep copy, Abstract classes | ex00 Β· ex01 Β· ex02 |
| CPP05 | Exceptions, try/catch, Abstract forms |
ex00 β ex03 |
| CPP06 | static_cast, reinterpret_cast, dynamic_cast |
ex00 Β· ex01 Β· ex02 |
| CPP07 | Function templates, Class templates | ex00 Β· ex01 Β· ex02 |
| CPP08 | easyfind, Span, MutantStack |
ex00 Β· ex01 Β· ex02 |
| CPP09 | map, stack, vector/deque, Ford-Johnson sort |
ex00 Β· ex01 Β· ex02 |
Your first step into C++ β discovering namespaces, classes, member functions, and the standard I/O stream.
A straightforward warm-up: takes command-line arguments and prints them in ALL CAPS. If no argument is given, it shouts the classic feedback noise.
$ ./megaphone "hello world"
HELLO WORLD
Concepts: std::cout, toupper, command-line arguments.
An interactive phonebook application stored entirely in memory (no file persistence). Supports two commands:
ADDβ adds a new contact (up to 8 slots, oldest is overwritten)SEARCHβ displays a formatted list, then lets you inspect a contact by index
Classes: Contact (stores name, phone number, darkest secret) Β· PhoneBook (manages up to 8 contacts)
Concepts: Classes, member functions, std::cin, string formatting, field truncation with ....
Re-implements the Account class so that its output exactly matches a provided log file (19920104_091532.log). A reverse-engineering exercise to understand class design from observable behavior.
Concepts: static members, constructor/destructor ordering, formatted output.
Who controls memory controls the program. Learn to create objects on the heap and the stack, and master the difference between references and pointers.
Introduces heap vs. stack allocation through a Zombie class that announces itself.
newZombie()β allocates on the heap, returns the pointer (caller manages lifetime)randomChump()β allocates on the stack (destroyed at end of scope)
Concepts: new, delete, constructors/destructors, scope lifetime.
Allocates a horde of N zombies in a single new[] call β demonstrating contiguous heap allocation.
Concepts: new[], delete[], array of objects.
Explores the equivalence of a pointer and a reference to the same variable, printing the address and value through both.
Concepts: Pointer vs. reference, address-of operator &, dereferencing.
HumanA holds its Weapon by reference (always has one), while HumanB holds it by pointer (may not have one). Both can attack() with their weapon.
Concepts: Reference vs. pointer members, when each is appropriate.
Opens an input file, replaces every occurrence of a string s1 with s2, and writes the result to <filename>.replace β without using std::string::replace.
Concepts: File I/O (std::ifstream, std::ofstream), string manipulation.
Harl complains at four severity levels: DEBUG, INFO, WARNING, ERROR. Instead of a long if/else chain, the complain() method dispatches using an array of pointers to member functions.
Concepts: Pointers to member functions, dispatch tables.
Filters Harl's output using a switch statement on the log level β once a level is matched, all higher-severity levels also print (fall-through behavior).
Concepts: switch/case, fall-through, string-to-enum mapping.
Numbers with fractional parts β but without floating-point hardware. Learn the Orthodox Canonical Form and make your class behave like a native type.
Introduces the Fixed class representing a fixed-point number (8 fractional bits) using an int as storage. Implements the Orthodox Canonical Form: default constructor, copy constructor, copy assignment operator, destructor.
Concepts: OCF, static const members, getRawBits()/setRawBits().
Extends Fixed with constructors that accept int and float, plus toFloat() and toInt() conversion methods. Also overloads operator<< for easy printing.
Concepts: Implicit conversions, static_cast, bit shifting, stream operators.
The full-featured Fixed class with:
- All six comparison operators (
>,<,>=,<=,==,!=) - All four arithmetic operators (
+,-,*,/) - Pre/post increment and decrement operators
staticmin()andmax()functions
Concepts: Operator overloading, const and non-const overloads.
Build a hierarchy of game characters, each more powerful than the last β by inheriting and extending.
All three exercises center on a game-inspired class family. Each derived class calls the parent constructor and extends behavior.
The base class for a simple robot fighter:
| Attribute | Value |
|---|---|
| Hit Points | 10 |
| Energy Points | 10 |
| Attack Damage | 0 |
Methods: attack(), takeDamage(), beRepaired().
ScavTrap inherits from ClapTrap, overrides stats and introduces guardGate().
| Attribute | Value |
|---|---|
| Hit Points | 100 |
| Energy Points | 50 |
| Attack Damage | 20 |
Concepts: Public inheritance, constructor/destructor chaining, method overriding.
FragTrap inherits from ClapTrap with its own stats and highFivesGuys() method.
| Attribute | Value |
|---|---|
| Hit Points | 100 |
| Energy Points | 100 |
| Attack Damage | 30 |
Concepts: Same inheritance mechanics, reinforcing the pattern.
A dog says woof. A cat says meow. But what does an Animal say? Welcome to virtual dispatch.
Animal is a base class with a virtual makeSound(). Dog and Cat override it. WrongAnimal/WrongCat demonstrate what happens without virtual β the base class method is called regardless.
Concepts: virtual, vtable, upcasting, WrongAnimal counter-example.
Each Dog and Cat now owns a Brain object (an array of 100 std::string ideas). Deep copy is required: the copy constructor and assignment operator must copy the Brain content, not just the pointer.
Concepts: Deep copy vs. shallow copy, pointer ownership.
Animal::makeSound() becomes pure virtual (= 0), making Animal an abstract class that cannot be instantiated directly. Only Dog and Cat can be instantiated.
Concepts: Pure virtual functions, abstract classes, interface design.
When things go wrong, throw an exception. When an exception is thrown, catch it gracefully.
The entire module revolves around a bureaucratic universe of Bureaucrats and Forms.
Bureaucrat has a const name and a grade (1 = highest, 150 = lowest). Attempting to set a grade out of range throws GradeTooHighException or GradeTooLowException.
Concepts: Custom exception classes, std::exception, what(), try/catch.
Form has a name, a sign grade, and an execute grade. Bureaucrat::signForm() tries to sign it; if the bureaucrat's grade is too low, it throws.
Concepts: Exception propagation, const member variables.
AForm becomes an abstract base class. Three concrete forms are implemented:
| Form | Sign Grade | Exec Grade | Effect |
|---|---|---|---|
ShrubberyCreationForm |
145 | 137 | Creates a file with ASCII trees |
RobotomyRequestForm |
72 | 45 | 50% chance of successful robotomy |
PresidentialPardonForm |
25 | 5 | Announces a presidential pardon |
Concepts: Abstract base classes, pure virtual execute(), polymorphism + exceptions.
Intern can create any of the three forms by name using a dispatch table of function pointers β no if/else chains.
Concepts: Intern factory pattern, array of function pointers, scalable dispatch.
C++ offers four named cast operators. Know when to use each one β and when not to.
ScalarConverter is a non-instantiable utility class (all constructors private). Its static convert() method accepts a string literal representing a scalar value and outputs the equivalent char, int, float, and double.
Handles special cases: nan, nanf, +inf, -inf, non-displayable characters.
Cast used: static_cast
Serializer converts a Data* pointer to a uintptr_t integer via serialize() and back via deserialize() β demonstrating that the original pointer is recovered.
Cast used: reinterpret_cast
generate() randomly creates an A, B, or C object (all deriving from Base) and returns it as a Base*. The two identify() overloads β one taking a pointer, one a reference β determine the real derived type at runtime.
Cast used: dynamic_cast, typeid
Write once, run with any type. Templates are C++'s answer to generic programming.
Three function templates that work with any type supporting comparison and assignment:
template <typename T> void swap(T& a, T& b);
template <typename T> T min(T a, T b);
template <typename T> T max(T a, T b);A function template iter() that applies a given function to every element of an array:
template <typename T, typename T1>
void iter(T array[], int length, void (func)(T1&));A fully-featured template class Array<T> that:
- Allocates elements with
new T[n] - Provides
operator[]with bounds checking (throwsOut_Of_Range) - Implements the Orthodox Canonical Form
- Tracks its own size via
T_size()
Concepts: Class templates, template specialization, exception-safe indexing.
The STL is your toolbox. Learn to use and extend it.
A function template easyfind<T> that searches any first-class container for an integer. Throws NonExistException if not found.
template <typename T>
void easyfind(T& container, int value);Span stores up to N integers and can report:
shortestSpan()β minimum difference between any two stored numberslongestSpan()β maximum difference between any two stored numbers
Internally backed by std::vector<int> and uses std::sort + std::min_element/std::max_element.
Concepts: STL algorithms, range-based insertion, exception handling for capacity and insufficient elements.
MutantStack<T> inherits from std::stack<T> and adds iterator support by exposing begin() and end() from the underlying container (std::deque by default).
template <typename T>
class MutantStack : public std::stack<T> { ... };Concepts: Adapter pattern, exposing protected members, iterator typedefs.
The final boss: apply the right container for the job, and implement a legendary sorting algorithm.
Reads a CSV database of historical BTC prices and an input file of date | value pairs. For each input line, it finds the closest earlier date in the database and prints date => value = result.
- Parses and validates dates and values rigorously
- Uses
std::multimap<Date, std::string>for ordered date lookup
$ ./btc input.txt
2011-01-03 => 3 = 0.9
2011-01-09 => 1 = 1
...
Containers: std::map, std::multimap
A stack-based RPN calculator. Accepts a mathematical expression in postfix notation and evaluates it.
$ ./RPN "8 9 * 9 - 9 - 9 - 4 - 1 +"
42
$ ./RPN "7 7 * 7 -"
42
Container: std::stack<int>
Implements the Ford-Johnson merge-insert sort algorithm β one of the most comparison-efficient sorting algorithms known β using two different containers and measures the time taken by each.
$ ./PmergeMe 3 5 9 7 4 1 2
Before: 3 5 9 7 4 1 2
After : 1 2 3 4 5 7 9
Time to process with std::vector : 0.00031 us
Time to process with std::deque : 0.00029 us
Containers: std::vector<std::pair<int,int>> and std::deque<std::pair<int,int>>
Algorithm steps:
- Build pairs and recursively sort the larger elements
- Insert smaller elements using the Jacobsthal sequence for optimal binary insertion order
Every exercise has its own Makefile. Navigate to the exercise directory and run:
# Build
make
# Run (example)
./megaphone "hello 42"
# Clean object files
make clean
# Remove binary too
make fclean
# Rebuild from scratch
make reCompiler flags used:
c++ -Wall -Wextra -Werror -std=c++98
shebaz β 1337 School student