[2026] C++ One Definition Rule (ODR): Multiple Definitions, inline, and Headers

[2026] C++ One Definition Rule (ODR): Multiple Definitions, inline, and Headers

이 글의 핵심

The ODR requires a single definition across the program for variables and functions, with exceptions for inline, templates, and C++17 inline variables. Avoid multiple definition link errors.

Introduction

1. Basic ODR rules

Variables

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// ❌ ODR violation
// file1.cpp
int globalVar = 10;
// file2.cpp
int globalVar = 20;  // multiple definitions

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.

// ✅ Correct pattern
// header.h
extern int globalVar;  // declaration
// file1.cpp
int globalVar = 10;   // single definition
// file2.cpp
#include "header.h"   // declaration only

Functions

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// ❌ Two definitions of the same function
// file1.cpp
void func() { std::cout << "file1\n"; }
// file2.cpp
void func() { std::cout << "file2\n"; }

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// ✅ Declaration in header, single definition in one .cpp
// header.h
void func();
// file1.cpp
void func() { std::cout << "implementation\n"; }

2. ODR exceptions

inline functions

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// utils.h
inline int add(int a, int b) {
    return a + b;
}
// file1.cpp
#include "utils.h"
// file2.cpp
#include "utils.h"  // OK if identical

Key point: inline definitions may appear in multiple TUs if token-identical.

Templates

Templates are typically defined in headers and instantiated in multiple TUs—ODR allows this under the usual rules for templates.

constexpr / inline variables (C++17)

inline constexpr int MAX = 100;  // single definition across TUs (C++17 inline variable)

3. Practical examples

Example 1: Global configuration

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

// config.h
#ifndef CONFIG_H
#define CONFIG_H
extern int maxConnections;
extern const char* appName;
inline int maxRetries = 3;
#endif

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.

// config.cpp
#include "config.h"
int maxConnections = 100;
const char* appName = "MyApp";

Example 2: Class in header, members in .cpp

Class definitions in headers must be identical in every TU that sees them—normally one shared header.

Example 3: static data members

Pre-C++17: define non-inline static data members in one .cpp. C++17 allows inline static members in-class.

4. Common problems

Problem 1: Non-inline function definitions in headers

Put non-inline definitions in a single .cpp, or mark small functions inline in the header.

Problem 2: Different definitions of the same type

If two TUs define struct Data differently, ODR is violated and behavior is undefined even if it “compiles.” Fix: define shared types in one header included everywhere.

Problem 3: Anonymous namespaces in headers

Each TU gets its own anonymous namespace—avoid putting headers in headers that should share state.

Problem 4: constexpr variables before C++17

Prefer inline constexpr in C++17+ for header-defined constants with a single-definition guarantee.

5. ODR-friendly patterns

Header / source split

Declarations and inline/template in headers; non-inline function bodies in one .cpp.

Logging helpers as inline in headers

Short inline void log(...) in headers is a common pattern.

6. Library-style example

Singleton or logger patterns: declare static members appropriately; define inline static in-class when possible (C++17).

7. Detecting violations

  • Linker: multiple definition of ...
  • nm across .o files for duplicate strong symbols
  • Warnings: -Wall -Wextra

Summary

  1. ODR — generally one definition.
  2. Variables — one definition; extern in headers for declarations.
  3. Functions — one definition unless inline/template rules apply.
  4. Classes — identical definitions in every TU.
  5. Exceptionsinline, templates, inline variables (C++17).

Quick reference

ItemHeaderSource
Variable declarationextern int var;int var = 0;
Function declarationvoid f();void f() {}
Class definitionclass C {};
inline functioninline void f() {}
Templatefull definition in header
Next: Extern linkage, Header files, Function overloading.

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3