मुझे लगता है कि जो सीमा आपने मानी है वह शब्दार्थ से संबंधित नहीं है (एक ही फ़ाइल में आरंभीकरण को परिभाषित करने पर कुछ क्यों बदलना चाहिए?) लेकिन सी ++ संकलन मॉडल के बजाय, जो कि पिछड़े संगतता के कारणों के लिए, इसे आसानी से नहीं बदला जा सकता है क्योंकि यह या तो बहुत जटिल हो जाते हैं (एक नए संकलन मॉडल और एक ही समय में मौजूदा का समर्थन करते हैं) या मौजूदा कोड को संकलित करने की अनुमति नहीं देंगे (एक नए संकलन मॉडल को शुरू करने और मौजूदा को छोड़ने के लिए)।
C ++ संकलन मॉडल C के उस से उपजा है, जिसमें आप (हेडर) फ़ाइलों को स्रोत फ़ाइल में घोषणाएँ आयात करते हैं। इस तरह, संकलक बिल्कुल एक बड़ी स्रोत फ़ाइल को देखता है, जिसमें सभी सम्मिलित फाइलें होती हैं, और उन फ़ाइलों से शामिल सभी फाइलें पुनरावर्ती होती हैं। इसका IMO एक बड़ा लाभ है, अर्थात् यह संकलक को लागू करने में आसान बनाता है। बेशक, आप शामिल फ़ाइलों में कुछ भी लिख सकते हैं, अर्थात घोषणा और परिभाषा दोनों। हेडर फ़ाइलों और परिभाषाओं में .c या .cpp फ़ाइलों में घोषणाएँ डालना एक अच्छा अभ्यास है।
दूसरी ओर, एक संकलन मॉडल होना संभव है जिसमें कंपाइलर अच्छी तरह से जानता है कि क्या वह एक वैश्विक प्रतीक की घोषणा को आयात कर रहा है जिसे किसी अन्य मॉड्यूल में परिभाषित किया गया है , या यदि वह एक वैश्विक प्रतीक की परिभाषा को संकलित कर रहा है। वर्तमान मॉड्यूल । केवल बाद के मामले में संकलक को इस प्रतीक (जैसे एक चर) को वर्तमान ऑब्जेक्ट फ़ाइल में रखना होगा।
उदाहरण के लिए, GNU पास्कल में आप इस तरह से a
एक फ़ाइल में एक इकाई लिख सकते हैं a.pas
:
unit a;
interface
var MyStaticVariable: Integer;
implementation
begin
MyStaticVariable := 0
end.
जहां वैश्विक चर घोषित किया जाता है और उसी स्रोत फ़ाइल में प्रारंभ किया जाता है।
तब आपके पास अलग-अलग इकाइयाँ हो सकती हैं जो वैश्विक चर का उपयोग और आयात करती हैं
MyStaticVariable
, जैसे एक इकाई b ( b.pas
):
unit b;
interface
uses a;
procedure PrintB;
implementation
procedure PrintB;
begin
Inc(MyStaticVariable);
WriteLn(MyStaticVariable)
end;
end.
और एक इकाई c ( c.pas
):
unit c;
interface
uses a;
procedure PrintC;
implementation
procedure PrintC;
begin
Inc(MyStaticVariable);
WriteLn(MyStaticVariable)
end;
end.
अंत में आप एक मुख्य कार्यक्रम में इकाइयों बी और सी का उपयोग कर सकते हैं m.pas
:
program M;
uses b, c;
begin
PrintB;
PrintC;
PrintB
end.
आप इन फ़ाइलों को अलग से संकलित कर सकते हैं:
$ gpc -c a.pas
$ gpc -c b.pas
$ gpc -c c.pas
$ gpc -c m.pas
और उसके बाद एक निष्पादन योग्य उत्पादन करें:
$ gpc -o m m.o a.o b.o c.o
और इसे चलाएं:
$ ./m
1
2
3
चाल यहाँ है कि जब संकलक देखता है एक है का उपयोग करता है एक कार्यक्रम मॉड्यूल में निर्देशक (जैसे b.pas में एक का उपयोग करता है), यह इसी .pas फ़ाइल शामिल नहीं है, लेकिन एक .gpi फ़ाइल, एक पूर्व संकलित के लिए यानी के लिए दिखता है इंटरफ़ेस फ़ाइल ( प्रलेखन देखें )। इन .gpi
फ़ाइलों को कंपाइलर द्वारा .o
फ़ाइलों के साथ मिलकर उत्पन्न किया जाता है जब प्रत्येक मॉड्यूल संकलित किया जाता है। तो वैश्विक प्रतीक MyStaticVariable
केवल ऑब्जेक्ट फ़ाइल में एक बार परिभाषित किया गया है a.o
।
जावा एक समान तरीके से काम करता है: जब कंपाइलर वर्ग A को वर्ग B में आयात करता है, तो यह A के लिए वर्ग फ़ाइल को देखता है और उसे फ़ाइल की आवश्यकता नहीं होती है A.java
। इसलिए कक्षा ए के लिए सभी परिभाषाएँ और इनिशियलाइज़ेशन को एक स्रोत फ़ाइल में रखा जा सकता है।
C ++ पर वापस जाने का कारण, C ++ में कारण यह है कि आपको एक अलग फ़ाइल में स्थिर डेटा सदस्यों को परिभाषित करना है जो कि सी ++ संकलन मॉडल से अधिक संबंधित है, जो लिंकर या कंपाइलर द्वारा उपयोग किए गए अन्य टूल द्वारा लगाई गई सीमाओं से अधिक है। सी ++ में, कुछ प्रतीकों को आयात करने का मतलब है कि वर्तमान संकलन इकाई के हिस्से के रूप में अपनी घोषणा का निर्माण करना। यह अन्य चीजों के बीच बहुत महत्वपूर्ण है, क्योंकि जिस तरह से टेम्पलेट संकलित किए जाते हैं। लेकिन इसका मतलब यह है कि आप किसी भी फ़ाइल में किसी भी वैश्विक प्रतीकों (फ़ंक्शन, चर, विधियों, स्थैतिक डेटा सदस्यों) को परिभाषित नहीं कर सकते हैं / नहीं करना चाहिए, अन्यथा इन प्रतीकों को संकलित ऑब्जेक्ट फ़ाइलों में गुणा-परिभाषित किया जा सकता है।