Ugrás a tartalomhoz

One Definition Rule

A Wikiszótárból, a nyitott szótárból


Főnév

One Definition Rule (tsz. One Definition Rules)

  1. (informatika) A One Definition Rule (röviden: ODR) a C++ nyelv egyik alapvető szabálya, amely kimondja:

Egy programon belül **minden típusnak, függvénynek, változónak vagy inline függvénynek pontosan egy definitív definíciója lehet – még akkor is, ha több fordítási egységből (translation unit) áll.

Ez a szabály garantálja a típusbiztonságot, az összeállítás helyességét, és azt, hogy a program deterministán viselkedjen.



🧠 Röviden: mi a definíció?

A deklaráció csak kijelenti, hogy létezik valami:

extern int x;   // deklaráció – nincs tárhely
int f();        // függvény deklaráció

A definíció létre is hozza az entitást:

int x = 5;      // definíció – tárhely is foglalva
int f() { ... } // függvénydefiníció

Az ODR azt mondja: csak egy definíció lehet, különben undefined behavior (UB) keletkezik.



📦 Mire vonatkozik az ODR?

Az ODR különböző entitásokra vonatkozik:

Entitás ODR érvényes? Megjegyzés
class vagy struct ✅ Igen Csak egy definitív definíció lehet, de több deklaráció
inline függvény ✅ Igen Többször előfordulhat, de bitazonos kell legyen
template definíció ✅ Igen Fordítási egységekben azonosnak kell lennie
constexpr funkció ✅ Igen Ugyanaz a szabály, mint inline-nál
const globális változó ✅ Igen const globálisként csak a translation unit-on belül látható, ha nincs extern
non-const globális változó ✅ Igen Csak egyszer definiálható az egész programban



🔧 Példa ODR megsértésére

// file1.cpp
int x = 5;

// file2.cpp
int x = 10;

// → undefined behavior

Ha file1.o és file2.o össze van linkelve, az x változónak két különböző definíciója van – ez megsérti az ODR-t.



✅ Hogyan lehet helyesen megosztani?

Használj deklarációt a header fájlban, és definíciót egy .cpp fájlban:

// x.h
extern int x;

// x.cpp
int x = 5;

// main.cpp
#include "x.h"

Így az x változónak csak egy definíciója lesz (x.cpp), és több deklarációja (extern int x;).



🏗️ ODR osztályokra

// myclass.h
struct MyClass {
    void hello();
};

// myclass.cpp
#include "myclass.h"
void MyClass::hello() {
    std::cout << "Hello!\n";
}

Ez megfelel az ODR-nek: csak egy osztálydefiníció, és külön implementáció.



🚨 Mikor sérül az ODR?

1. Többszörösen beillesztett definíciók

// myheader.h
int global = 5;

// main.cpp
#include "myheader.h"
#include "other.cpp"

// other.cpp
#include "myheader.h"

Itt global kétszer lesz definiálva: megsérti az ODR-t.

👉 Megoldás: használj extern kulcsszót headerben, és tényleges definíciót .cpp-ben.



🧪 Inline függvények és ODR

Az inline függvények többször definiálhatók, de a definíciójuknak pontosan azonosnak kell lennie minden fordítási egységben.

// utils.h
inline int square(int x) {
    return x * x;
}

Ez megengedett, de minden .cpp fájlban azonos kód kell legyen.

Ha eltér:

// file1.cpp
inline int square(int x) { return x * x; }

// file2.cpp
inline int square(int x) { return x + x; }

// → undefined behavior

🧱 Template-ek és ODR

A sablonokat (template<class T>) a fordító példányosítja minden típusra. Ezek is ODR-nek vannak alávetve: azonos sablonpéldány ugyanolyan kódot kell adjon minden .cpp-ben.

Ha egy template<class T> osztály vagy függvény két fájlban különböző implementációt kap: sértés.



🎯 C++11 és újabb: inline változók

// config.h
inline int version = 1;

Ez C++17-től megengedett, és nem sérti az ODR-t – minden fordítási egység láthatja.



🧭 Összegzés

Fogalom Jelentés
ODR (One Definition Rule) Minden entitásnak pontosan egy definíciója lehet
Többszörös deklaráció ✅ megengedett
Többszörös definíció ❌ tilos, kivéve inline, template, constexpr stb.
Violáció eredménye Undefined behavior (UB)
Megoldás extern + .cpp definíció
C++17 újdonság inline változók



🧠 Zárógondolat

Az ODR a C++ linkelési modellének alapja. Ha megsértjük, nincs garantált működés – a program fordulhat, de futás közben hibásan viselkedik. Ezért fontos az extern, a header.cpp szétválasztás, az inline és a #pragma once vagy include guard tudatos használata.