आप वैश्विक चर होना आवश्यक है, तो सामान्य अभ्यास के लिए उन्हें एक ज फ़ाइल में घोषित करने और उन्हें एक (और केवल एक) .cpp फ़ाइल में परिभाषित करने के लिए है।
एक .h फ़ाइल में;
extern int x;
एक .cpp फ़ाइल में;
int x=3;
मैं पूर्णांक का इस्तेमाल किया है (सबसे मौलिक बुनियादी प्रकार शायद?) के बजाय स्थिरांक चार * अपने उदाहरण के रूप में आपकी समस्या का सार चर के प्रकार पर निर्भर नहीं करता है क्योंकि।
मूल विचार यह है कि आप एक चर कई बार घोषित कर सकते हैं, इसलिए प्रत्येक .cpp फ़ाइल जिसमें .h फ़ाइल शामिल है वेरिएबल घोषित करती है, और यह ठीक है। लेकिन आप इसे केवल एक बार परिभाषित करते हैं। परिभाषा वह बयान है जहां आप वैरिएबल प्रारंभिक मान असाइन करते हैं, (एक = के साथ)। आप .h फ़ाइलों में परिभाषा नहीं चाहते हैं, क्योंकि तब .h फ़ाइल एकाधिक .cpp फ़ाइलों द्वारा शामिल की जाती है, तो आपको कई परिभाषाएं मिलेंगी। यदि आपके पास एक चर के एकाधिक परिभाषाएं हैं, तो लिंक समय पर एक समस्या है क्योंकि लिंकर चर के पते को असाइन करना चाहता है और यदि इसकी कई प्रतियां हैं तो उचित रूप से ऐसा नहीं कर सकता है।
सूड के भ्रम को आजमाने और आसानी से जोड़ने के लिए अतिरिक्त जानकारी बाद में जोड़ा गया;
इसे बेहतर समझने के लिए अपनी समस्या को कम से कम भागों में कम करने का प्रयास करें;
कल्पना कीजिए कि आपके पास एक प्रोग्राम है जिसमें तीन .cpp फ़ाइलें शामिल हैं। प्रोग्राम बनाने के लिए प्रत्येक .cpp को तीन ऑब्जेक्ट फ़ाइलों को बनाने के लिए अलग से संकलित किया जाता है, फिर तीन ऑब्जेक्ट फ़ाइलें एक साथ जुड़ी होती हैं। यदि तीन .cpp फ़ाइलें निम्नानुसार हैं (उदाहरण ए, अच्छा संगठन);
file1.cpp
extern int x;
file2.cpp
extern int x;
file3.cpp
extern int x;
तब फ़ाइलें संकलन और समस्या के बिना एक साथ लिंक (कम से कम जहाँ तक होगा परिवर्तनीय एक्स चिंतित है)। कोई समस्या नहीं है क्योंकि प्रत्येक फ़ाइल केवल परिवर्तनीय एक्स घोषित कर रही है। एक घोषणा बस यह बता रही है कि वहां कहीं भी एक चर है जो मैं (या नहीं) उपयोग कर सकता हूं।
एक ही चीज़ प्राप्त करने का एक बेहतर तरीका निम्नलिखित है (उदाहरण ए, बेहतर संगठन);
header.h
extern int x;
file1.cpp
#include "header.h"
file2.cpp
#include "header.h"
file3.cpp
#include "header.h"
यह तीनों संकलनों में से प्रत्येक के लिए प्रभावी रूप से वही है, क्योंकि संकलक पहले से ही उसी पाठ को देखता है क्योंकि यह .cpp फ़ाइल (या अनुवाद इकाई के रूप में अनुवाद इकाई) को संसाधित करता है, क्योंकि # अंतर्निहित निर्देश केवल दूसरे से टेक्स्ट खींचता है फ़ाइल। फिर भी यह पहले के उदाहरण पर एक सुधार है क्योंकि हमारे पास केवल एक फ़ाइल में हमारी घोषणा है, न कि कई फाइलों में।
अब एक और कामकाजी उदाहरण (उदाहरण बी, अच्छा संगठन) पर विचार करें;
file1.cpp
extern int x;
file2.cpp
extern int x;
file3.cpp
extern int x;
int x=3;
यह ठीक रूप में अच्छी तरह से काम करेगा। सभी तीन .cpp फ़ाइलें x घोषित करती हैं और एक वास्तव में इसे परिभाषित करता है। हम आगे बढ़ सकते हैं और वेरिएबल एक्स में हेरफेर करने वाली तीन फाइलों में से किसी एक में फ़ंक्शंस के भीतर और कोड जोड़ सकते हैं और हमें कोई त्रुटि नहीं मिलेगी। फिर हमें एक हेडर फ़ाइल का उपयोग करना चाहिए ताकि घोषणा केवल एक भौतिक फ़ाइल (उदाहरण बी, बेहतर संगठन) में हो।
header.h
extern int x;
file1.cpp
#include "header.h"
file2.cpp
#include "header.h"
file3.cpp
#include "header.h"
int x=3;
अंत में एक उदाहरण पर विचार करें जो सिर्फ काम नहीं करेगा (उदाहरण सी, काम नहीं करता है);
file1.cpp
int x=3;
file2.cpp
int x=3;
file3.cpp
int x=3;
प्रत्येक फ़ाइल समस्याओं के बिना संकलन होगा। समस्या लिंक समय पर होती है क्योंकि अब हमारे पास परिभाषित तीन अलग int x चर हैं। एक ही नाम है और सभी वैश्विक रूप से दिखाई दे रहे हैं। लिंकर का काम एक ही प्रोग्राम के लिए आवश्यक सभी ऑब्जेक्ट्स को एक निष्पादन योग्य में खींचना है। वैश्विक रूप से दृश्यमान वस्तुओं का एक अनूठा नाम होना चाहिए, ताकि लिंकर निष्पादन योग्य में एक परिभाषित पते (स्थान) पर ऑब्जेक्ट की एक प्रतिलिपि रख सके और अन्य सभी ऑब्जेक्ट्स को उस पते पर एक्सेस करने दें। लिंकर इस मामले में ग्लोबल वेरिएबल एक्स के साथ अपना काम नहीं कर सकता है और इसके बजाए एक त्रुटि को चकित कर देगा।
अलग-अलग परिभाषाओं को एक तरफ देने के रूप में विभिन्न प्रारंभिक मान समस्या का समाधान नहीं करते हैं। कीवर्ड स्थैतिक के साथ प्रत्येक परिभाषा से पहले समस्या का समाधान होता है क्योंकि अब चर वैश्विक रूप से दिखाई नहीं दे रहे हैं, बल्कि .cpp फ़ाइल में परिभाषित किए गए हैं।
यदि आप एक शीर्षलेख फ़ाइल में वैश्विक चर परिभाषा डालते हैं, कुछ भी आवश्यक नहीं बदला है (उदाहरण सी, हेडर संगठन इस मामले में सहायक नहीं है);
header.h
int x=3; // Don't put this in a .h file, causes multiple definition link error
file1.cpp
#include "header.h"
file2.cpp
#include "header.h"
file3.cpp
#include "header.h"
पुhew, मुझे उम्मीद है कि कोई इसे पढ़ता है और इससे कुछ लाभ मिलता है। कभी-कभी प्रश्नकर्ता बुनियादी अवधारणाओं के संदर्भ में एक सरल व्याख्या के लिए रो रहा है जो एक उन्नत कंप्यूटर वैज्ञानिक की व्याख्या नहीं है। के बाद से यह एक वस्तु COUNTRY_NAME_USA
के परिभाषा साथ हेडर फाइल में बाहरी संबंध बनाता है
लेकिन क्या होगा अगर मैं नीचे हेडर फाइल सिर्फ एक बार शामिल करने के लिए, मैं अभी भी लिंकर समय त्रुटियों होगा: #ifndef MY_HDR_FILE_H_ #define MY_HDR_FILE_H_ #endif, अगर मैं न मेरी घोषणा – sud
@sud में 2 स्थिरांक है: मैं बात कर रहा हूँ * अलग * अनुवाद इकाइयों में हेडर फ़ाइल को शामिल करने के बारे में। आपके '# ifndef' गार्ड के पास इसके साथ कुछ भी करने के लिए बिल्कुल कुछ नहीं है, यह होने से रोका नहीं जा सकता है और इससे कोई फर्क नहीं पड़ता। आपको पहले संस्करण के साथ एक ही लिंकर त्रुटियां मिलेंगी। – AnT
@ एंड्रे: स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। आपकी टिप्पणी में आपने उल्लेख किया है कि "const char * const COUNTRY_NAME_USA =" यूएसए "है;" एक एचडीआर फ़ाइल में सबसे अच्छा होगा, लेकिन प्रत्येक अनुवाद इकाई को अपना खुद का अंतराल मिलेगा। क्या इसका मतलब यह है कि रनटाइम पर प्रभावशाली मुद्दे होंगे। मेरा मतलब है कि निष्पादन योग्य आकार बड़ा हो क्योंकि प्रत्येक ट्रांसलेशन इकाई की अपनी प्रतिलिपि है? इसके अलावा डीबगिंग के दौरान मैं कोर डंप में चार पॉइंटर का पता देख पाऊंगा। – sud