Zostałem ukąszony przez nieprzyjemne naruszenie zasady "jednej definicji". Obecnie obawiam się, że w moich projektach mam wiele subtelnych błędów.Jedno ostrzeżenie o definicji definicji
Na przykład, poniższy program spowoduje null pointer dereference z Visual Studio 2015:
Source1.cpp:
----------
struct S {
double d = 0;
};
void Foo() {
S s;
}
Source2.cpp:
-----------
struct S {
int a = 0;
};
int main() {
int value = 5;
int& valueRef = value;
S s; // valueRef is erased due to S::d initialization from Source1.cpp
valueRef++; // crash
}
To kompiluje bez ostrzeżenia.
Jest nieprzyjemny, ponieważ Source2.cpp
nie używa niczego od Source1.cpp
. Jeśli usunę z projektu Source1.cpp
, nadal się kompiluje i nie ma już problemu.
W dużych projektach wydaje się bardzo trudne zapewnienie, że żaden plik cpp "lokalnie" nie definiuje struktury lub klasy o już zdefiniowanej nazwie.
Mam kilka klas, takich jak Point
, Serie
, State
, Item
... I chociaż to było OK w małych plików CPP, ale zdaję sobie sprawę, że nie jest bezpieczne.
Czy istnieje ostrzeżenie o kompilatorach do wychwytywania takich błędów? Jeśli nie, jakie są najlepsze praktyki, aby uniknąć naruszenia ODR?
Definiowanie ich w anonimowym obszarze nazw. – molbdnilo