[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
The One Definition Rule (ODR) states that variables, functions, classes, etc. must have one definition in the program (with well-known exceptions). Understanding ODR prevents link errors and subtle bugs.
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 ... nmacross.ofiles for duplicate strong symbols- Warnings:
-Wall -Wextra
Summary
- ODR — generally one definition.
- Variables — one definition;
externin headers for declarations. - Functions — one definition unless
inline/template rules apply. - Classes — identical definitions in every TU.
- Exceptions —
inline, templates,inlinevariables (C++17).
Quick reference
| Item | Header | Source |
|---|---|---|
| Variable declaration | extern int var; | int var = 0; |
| Function declaration | void f(); | void f() {} |
| Class definition | class C {}; | — |
| inline function | inline void f() {} | — |
| Template | full definition in header | — |
| Next: Extern linkage, Header files, Function overloading. |