# Headers, Source Files, Namespaces and the ODR — C++

Source: https://www.skillbyai.com/en/cpp/c-structure

> Organise code into headers and source files with namespaces, and avoid ODR violations.

## Splitting a program across files

C++ code is traditionally split into **headers** (`.h` or `.hpp`) containing **declarations** (what exists: function signatures, class definitions, templates) and **source files** (`.cpp`) containing **definitions** (the function bodies). Other files `#include` the header to use the declarations, and the linker connects them to the definitions. Protect headers from being included twice in one translation unit with **include guards** or the widely supported **`#pragma once`**. The **One Definition Rule (ODR)** says each non-inline function or variable must be defined exactly **once** in the whole program; defining a normal function in a header included by two `.cpp` files causes a "multiple definition" link error. Templates, `inline` functions, `constexpr` functions and class definitions may appear in headers because they are allowed in multiple translation units if identical. **Namespaces** (`namespace shop { ... }`) group related names and prevent clashes; avoid `using namespace std;` in headers, where it leaks into every file that includes them. **C++20 modules** (`export module geometry;`) aim to replace headers with faster, cleaner imports, and compiler support has been improving steadily.

## A header, its source file and a user

Declarations in the header, definitions in one .cpp file.

```cpp
// geometry.hpp
#pragma once
#include <string>

namespace geo {
    struct Point { double x{}; double y{}; };
    double distance(const Point& a, const Point& b);    // declaration
    std::string to_string(const Point& p);
    inline double square(double v) { return v * v; }     // inline: OK in a header
}

// geometry.cpp
#include "geometry.hpp"
#include <cmath>
#include <format>

namespace geo {
    double distance(const Point& a, const Point& b) {      // the one definition
        return std::sqrt(square(a.x - b.x) + square(a.y - b.y));
    }
    std::string to_string(const Point& p) { return std::format("({}, {})", p.x, p.y); }
}

// main.cpp
#include "geometry.hpp"
#include <print>
int main() {
    geo::Point a{0, 0}, b{3, 4};
    std::print("{} to {} is {}\n", geo::to_string(a), geo::to_string(b), geo::distance(a, b));
}
```

## Never put using namespace std in a header

It injects every standard name into every file that includes your header, causing confusing ambiguities with names like `count`, `distance` or `size`. In source files, prefer specific `using std::string;` declarations or just write `std::`.

**Quiz:** Why does defining a non-inline function in a header included by two source files cause a link error?

- [x] It violates the One Definition Rule: the function is defined twice in the program
- [ ] Headers cannot contain functions
- [ ] The compiler ignores headers
- [ ] Namespaces are missing

*Answer:* It violates the One Definition Rule: the function is defined twice in the program. Each translation unit gets its own definition, so the linker finds duplicate symbols.
