C++ One Definition Rule : Multiple Definitions, inline,
이 글의 핵심
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
// ❌ ODR violation
// file1.cpp
int globalVar = 10;
// file2.cpp
int globalVar = 20; // multiple definitions
// ✅ Correct pattern
// header.h
extern int globalVar; // declaration
// file1.cpp
int globalVar = 10; // single definition
// file2.cpp
#include "header.h" // declaration only
Functions
// ❌ Two definitions of the same function
// file1.cpp
void func() { std::cout << "file1\n"; }
// file2.cpp
void func() { std::cout << "file2\n"; }
// ✅ 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
// 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
// config.h
#ifndef CONFIG_H
#define CONFIG_H
extern int maxConnections;
extern const char* appName;
inline int maxRetries = 3;
#endif
// 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. |
Related posts
- C++ Compilation Process
- C++ multiple definition error
- C++ header-only library
- C++ Linking
- C++ Name Mangling
Frequently Asked Questions (FAQ)
Q. When would I use this in practice?
A. The ODR requires a single definition across the program for variables and functions, with exceptions for inline.
Q. What should I read before this?
A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the C++ series index for the full picture.
Q. Where can I study this more deeply?
A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.
Related Articles (Internal Links)
Other articles related to this topic.
- C++ Extern Linkage | ‘외부 연결’ 가이드
- C++ 함수 오버로딩 | ‘Function Overloading’ 가이드
- C++ Header Files | ‘헤더 파일’ 가이드
Keywords Covered in This Article (Related Search Terms)
This article covers C++, ODR, one definition rule, linking, inline.