JSTAcademy
0 XP
Dashboard
Crash Courses
Multi-File Project with Headers
60 min
PhD+200 XP
Crash Courses · PhD

Multi-File Project with Headers

Organise a real C++ project across .h and .cpp files
60 min read+200 XP on completionCert: C++ Crash Course
Tap any word in the text below to start reading from there.

Multi-File Project with Headers

Project Layout

calculator/
  mathlib.h      ← declarations
  mathlib.cpp    ← definitions
  main.cpp       ← entry point

mathlib.h

#pragma once  // include guard — prevents double inclusion

#include <stdexcept>

namespace mathlib {

class Calculator {
public:
    double add(double a, double b) const;
    double subtract(double a, double b) const;
    double multiply(double a, double b) const;
    double divide(double a, double b) const;   // throws on zero
    double power(double base, int exp) const;
};

// Inline function — definition stays in header
inline double square(double x) { return x * x; }

} // namespace mathlib

mathlib.cpp

#include "mathlib.h"

namespace mathlib {

double Calculator::add(double a, double b) const {
    return a + b;
}

double Calculator::subtract(double a, double b) const {
    return a - b;
}

double Calculator::multiply(double a, double b) const {
    return a * b;
}

double Calculator::divide(double a, double b) const {
    if (b == 0.0) {
        throw std::invalid_argument("Cannot divide by zero");
    }
    return a / b;
}

double Calculator::power(double base, int exp) const {
    double result = 1.0;
    bool negative = exp < 0;
    int  n = negative ? -exp : exp;
    for (int i = 0; i < n; ++i) result *= base;
    return negative ? 1.0 / result : result;
}

} // namespace mathlib

main.cpp

#include <iostream>
#include "mathlib.h"

int main() {
    mathlib::Calculator calc;

    std::cout << calc.add(3, 4)        << std::endl; // 7
    std::cout << calc.multiply(5, 6)   << std::endl; // 30
    std::cout << calc.power(2, 10)     << std::endl; // 1024
    std::cout << mathlib::square(7)    << std::endl; // 49

    try {
        calc.divide(1, 0);
    } catch (const std::exception& e) {
        std::cerr << "Caught: " << e.what() << std::endl;
    }

    return 0;
}

Compiling Multiple Files

# Compile each .cpp to an object file
g++ -std=c++17 -Wall -c mathlib.cpp -o mathlib.o
g++ -std=c++17 -Wall -c main.cpp    -o main.o

# Link object files into an executable
g++ mathlib.o main.o -o calculator

./calculator

Or in one step:

g++ -std=c++17 -Wall mathlib.cpp main.cpp -o calculator

Why Separate Compilation?

  • Incremental builds — only recompile changed files
  • Information hiding — users see the header (interface), not the implementation
  • Parallel compilation — build systems compile independent .cpp files simultaneously

Common Pitfalls

  1. Defining a non-inline function in a header — if two .cpp files include it, the linker sees two definitions and errors.
  2. Circular includes — A.h includes B.h includes A.h → use forward declarations to break cycles.
  3. Missing #pragma once — header included twice → redefinition errors.

Forward Declarations

// In A.h — instead of #include "B.h"
class B;  // forward declaration — enough if you only use B* or B& in A.h

class A {
    B* ptr; // ok with forward declaration
};
0%