C++
एक परिभाषा नियम (ODR)
खोज…
बहुविध रूप से परिभाषित कार्य
वन डेफिनिशन नियम का सबसे महत्वपूर्ण परिणाम यह है कि बाहरी लिंकेज वाले गैर-इनलाइन कार्यों को केवल एक कार्यक्रम में एक बार परिभाषित किया जाना चाहिए, हालांकि उन्हें कई बार घोषित किया जा सकता है। इसलिए, हेडर में ऐसे कार्यों को परिभाषित नहीं किया जाना चाहिए, क्योंकि हेडर को विभिन्न अनुवाद इकाइयों से कई बार शामिल किया जा सकता है।
foo.h
:
#ifndef FOO_H
#define FOO_H
#include <iostream>
void foo() { std::cout << "foo"; }
void bar();
#endif
foo.cpp
:
#include "foo.h"
void bar() { std:: cout << "bar"; }
main.cpp
:
#include "foo.h"
int main() {
foo();
bar();
}
इस कार्यक्रम में, समारोह foo
शीर्षक में परिभाषित किया गया है foo.h
है, जो दो बार शामिल किया गया है: एक बार से foo.cpp
और से एक बार main.cpp
। प्रत्येक अनुवाद इकाई में foo
की अपनी परिभाषा समाहित है। ध्यान दें कि में गार्ड शामिल foo.h
ऐसा होने से रोकने नहीं है, के बाद से foo.cpp
और main.cpp
दोनों को अलग-अलग foo.h
। इस कार्यक्रम को बनाने की कोशिश करने का सबसे संभावित परिणाम एक लिंक-टाइम त्रुटि है जो कि foo
को पहचानने में त्रुटि के रूप में परिभाषित किया गया है।
ऐसी त्रुटियों से बचने के लिए, किसी को हेडर में फ़ंक्शन की घोषणा करनी चाहिए और उन्हें इसी .cpp
फ़ाइलों में परिभाषित करना चाहिए, कुछ अपवादों के साथ (अन्य उदाहरण देखें)।
इनलाइन कार्य
एक inline
घोषित फ़ंक्शन को कई अनुवाद इकाइयों में परिभाषित किया जा सकता है, बशर्ते कि सभी परिभाषाएं समान हों। यह हर अनुवाद इकाई में परिभाषित किया जाना चाहिए जिसमें इसका उपयोग किया जाता है। इसलिए, इनलाइन फ़ंक्शन को हेडर में परिभाषित किया जाना चाहिए और कार्यान्वयन फ़ाइल में उनका उल्लेख करने की आवश्यकता नहीं है।
कार्यक्रम ऐसे व्यवहार करेगा जैसे कि फ़ंक्शन की एकल परिभाषा है।
foo.h
:
#ifndef FOO_H
#define FOO_H
#include <iostream>
inline void foo() { std::cout << "foo"; }
void bar();
#endif
foo.cpp
:
#include "foo.h"
void bar() {
// more complicated definition
}
main.cpp
:
#include "foo.h"
int main() {
foo();
bar();
}
इस उदाहरण में, हेडर फ़ाइल में सरल फ़ंक्शन foo
को इनलाइन परिभाषित किया गया है जबकि अधिक जटिल फ़ंक्शन bar
इनलाइन नहीं है और कार्यान्वयन फ़ाइल में परिभाषित किया गया है। दोनों foo.cpp
और main.cpp
अनुवाद इकाइयों की परिभाषा को शामिल foo
, लेकिन इस कार्यक्रम अच्छी तरह से गठित के बाद से है foo
इनलाइन है।
एक वर्ग परिभाषा के भीतर परिभाषित एक फ़ंक्शन (जो एक सदस्य फ़ंक्शन या एक मित्र फ़ंक्शन हो सकता है) स्पष्ट रूप से इनलाइन है। इसलिए, यदि किसी श्रेणी को हेडर में परिभाषित किया गया है, तो कक्षा के सदस्य कार्यों को वर्ग परिभाषा के भीतर परिभाषित किया जा सकता है, भले ही परिभाषाओं को कई अनुवाद इकाइयों में शामिल किया जा सकता है:
// in foo.h
class Foo {
void bar() { std::cout << "bar"; }
void baz();
};
// in foo.cpp
void Foo::baz() {
// definition
}
समारोह Foo::baz
, आउट-ऑफ-लाइन परिभाषित किया गया है, तो यह एक इनलाइन समारोह नहीं है, और हेडर में निर्धारित नहीं किया जाना चाहिए।
ओवरलोड रिज़ॉल्यूशन के माध्यम से ओडीआर उल्लंघन
इनलाइन फ़ंक्शंस के लिए समान टोकन के साथ भी, ODR का उल्लंघन किया जा सकता है यदि नामों की खोज एक ही इकाई को संदर्भित नहीं करती है। के विचार करते हैं func
निम्नलिखित में:
header.h
void overloaded(int); inline void func() { overloaded('*'); }
foo.cpp
#include "header.h" void foo() { func(); // `overloaded` refers to `void overloaded(int)` }
bar.cpp
void overloaded(char); // can come from other include #include "header.h" void bar() { func(); // `overloaded` refers to `void overloaded(char)` }
हमारे पास ओडीआर उल्लंघन है क्योंकि अनुवाद इकाई के आधार पर विभिन्न संस्थाओं को overloaded
जाता है।