हेडर के केवल लाइब्रेरी के क्या लाभ हैं और आप इसे इस तरह क्यों लिखेंगे कि कार्यान्वयन को अलग फ़ाइल में डालने का विरोध करें?
हेडर के केवल लाइब्रेरी के क्या लाभ हैं और आप इसे इस तरह क्यों लिखेंगे कि कार्यान्वयन को अलग फ़ाइल में डालने का विरोध करें?
जवाबों:
ऐसी स्थितियाँ होती हैं जब हेडर-ओनली लाइब्रेरी एकमात्र विकल्प होता है, उदाहरण के लिए जब टेम्प्लेट से निपटते हैं।
हेडर-ओनली लाइब्रेरी होने का मतलब यह भी है कि आपको उन विभिन्न प्लेटफार्मों के बारे में चिंता करने की ज़रूरत नहीं है जहाँ लाइब्रेरी का उपयोग किया जा सकता है। जब आप कार्यान्वयन को अलग करते हैं, तो आप आमतौर पर कार्यान्वयन विवरण छिपाने के लिए करते हैं, और लाइब्रेरी को हेडर और लाइब्रेरीज़ ( lib
, dll
's या .so
फ़ाइलों) के संयोजन के रूप में वितरित करते हैं । बेशक ये सभी विभिन्न ऑपरेटिंग सिस्टम / संस्करणों के लिए संकलित किए जाने हैं जिन्हें आप समर्थन प्रदान करते हैं।
आप कार्यान्वयन फ़ाइलों को भी वितरित कर सकते हैं, लेकिन इसका मतलब है कि उपयोगकर्ता के लिए एक अतिरिक्त कदम होगा - इसका उपयोग करने से पहले अपनी लाइब्रेरी को संकलित करना।
बेशक, यह मामला-दर-मामला आधार पर लागू होता है । उदाहरण के लिए, हेडर-ओनली लाइब्रेरी कभी-कभी बढ़ जाती हैकोड का आकार और संकलन समय।
हेडर-ओनली लाइब्रेरी के लाभ:
हेडर-ओनली लाइब्रेरी का नुकसान:
बड़ी वस्तु फ़ाइलें। लाइब्रेरी से प्रत्येक इनलाइन विधि जो किसी स्रोत फ़ाइल में उपयोग की जाती है, उस स्रोत फ़ाइल के लिए संकलित ऑब्जेक्ट फ़ाइल में एक कमजोर प्रतीक, आउट-ऑफ-लाइन परिभाषा प्राप्त करेगी। यह संकलक को धीमा कर देता है और लिंकर को भी धीमा कर देता है। कंपाइलर को वह सभी ब्लोट उत्पन्न करना होता है, और फिर लिंकर को इसे फ़िल्टर करना होता है।
लंबे समय तक संकलन। ऊपर उल्लिखित ब्लोट समस्या के अतिरिक्त, संकलन में अधिक समय लगेगा क्योंकि हेडर्स संकलित लाइब्रेरी की तुलना में हेडर-ओनली लाइब्रेरी के साथ स्वाभाविक रूप से बड़े हैं। उन बड़े हेडर को लाइब्रेरी का उपयोग करने वाली प्रत्येक स्रोत फ़ाइल के लिए पार्स करने की आवश्यकता होती है। एक और पहलू यह है कि हेडर-ओनली लाइब्रेरी में उन हेडर फाइल #include
को इनलाइन परिभाषाओं के साथ हेडर की जरूरत होती है और साथ ही हेडर की जरूरत होती है जो लाइब्रेरी को संकलित लाइब्रेरी के रूप में बनाया गया है।
अधिक पेचीदा संकलन। हेडर-ओनली लाइब्रेरी के साथ आपको बहुत अधिक निर्भरता मिलती है क्योंकि हेडर-ओनली लाइब्रेरी के साथ उन अतिरिक्त #include
एस की जरूरत होती है। लाइब्रेरी में कुछ प्रमुख फ़ंक्शन के कार्यान्वयन को बदलें और आपको पूरी परियोजना को फिर से तैयार करने की आवश्यकता हो सकती है। संकलित पुस्तकालय के लिए स्रोत फ़ाइल में वह परिवर्तन करें और आपको बस इतना करना है कि एक पुस्तकालय स्रोत फ़ाइल, उस नई .o फ़ाइल के साथ संकलित पुस्तकालय को अपडेट करें, और एप्लिकेशन को रिलेक्स करें।
मानव को पढ़ने के लिए कठिन। यहां तक कि सबसे अच्छे प्रलेखन के साथ, पुस्तकालय के पुस्तकालय के उपयोगकर्ताओं को पुस्तकालय के लिए शीर्षलेख पढ़ने का सहारा लेना पड़ता है। हेडर-ओनली लाइब्रेरी में हेडर कार्यान्वयन विवरणों से भरे होते हैं जो इंटरफ़ेस को समझने के तरीके से मिलते हैं। संकलित पुस्तकालय के साथ, आप जो कुछ भी देखते हैं वह इंटरफ़ेस और एक संक्षिप्त टिप्पणी है जो कार्यान्वयन करता है, और यह आमतौर पर आप सभी चाहते हैं। यह वास्तव में आप सभी को चाहिए। लाइब्रेरी का उपयोग कैसे करें, यह जानने के लिए आपको कार्यान्वयन विवरण नहीं जानना चाहिए।
detail
।
मुझे पता है कि यह एक पुराना धागा है, लेकिन किसी ने भी एबीआई इंटरफेस या विशिष्ट संकलक मुद्दों का उल्लेख नहीं किया है। तो मुझे लगा कि मैं करूंगा।
यह मूल रूप से आप की अवधारणा पर आधारित है या तो लोगों को वितरित करने के लिए एक हेडर के साथ एक पुस्तकालय लिख रहा है या अपने आप को पुन: उपयोग कर रहा है बनाम हेडर में सब कुछ है। यदि आप एक हेडर और सोर्स फाइल्स को पुनः प्रयोग करने और हर प्रोजेक्ट में इनका पुनः उपयोग करने की सोच रहे हैं तो यह वास्तव में लागू नहीं होता है।
मूल रूप से यदि आप अपना C ++ कोड संकलित करते हैं और एक संकलक के साथ एक पुस्तकालय का निर्माण करते हैं, तो उपयोगकर्ता एक अलग संकलक या उसी संकलक के एक अलग संस्करण के साथ उस पुस्तकालय का उपयोग करने की कोशिश करता है तो आपको बाइनरी अपूर्णता के कारण लिंकर त्रुटियों या अजीब क्रम व्यवहार मिल सकता है।
उदाहरण के लिए संकलक विक्रेता अक्सर संस्करणों के बीच एसटीएल के अपने कार्यान्वयन को बदलते हैं। यदि आपके पास लाइब्रेरी में कोई फ़ंक्शन है जो एक std :: वेक्टर को स्वीकार करता है, तो यह उम्मीद करता है कि उस कक्षा में बाइट्स को उसी तरह व्यवस्थित किया जाए जब वे लाइब्रेरी संकलित किए गए थे। यदि, एक नए संकलक संस्करण में, विक्रेता ने std :: वेक्टर के लिए दक्षता में सुधार किया है, तो उपयोगकर्ता का कोड नई कक्षा को देखता है जिसमें एक अलग संरचना हो सकती है और उस नई संरचना को आपके पुस्तकालय में पास कर सकती है। सब कुछ वहाँ से नीचे चला जाता है ... यही कारण है कि पुस्तकालय की सीमाओं के पार एसटीएल वस्तुओं को पारित नहीं करने की सिफारिश की जाती है। यही बात C रन-टाइम (CRT) प्रकारों पर लागू होती है।
सीआरटी के बारे में बात करते समय, आपके पुस्तकालय और उपयोगकर्ता के स्रोत कोड को आम तौर पर उसी सीआरटी के खिलाफ जोड़ा जाना चाहिए। Visual Studio के साथ यदि आप Multithreaded CRT का उपयोग करके अपनी लाइब्रेरी का निर्माण करते हैं, लेकिन उपयोगकर्ता Multithreaded Debug CRT के विरुद्ध लिंक करता है, तो आपको लिंक समस्याएँ होंगी क्योंकि आपकी लाइब्रेरी को वे प्रतीक नहीं मिल सकते हैं जिनकी उसे आवश्यकता है। मुझे याद नहीं है कि यह कौन सा समारोह था, लेकिन विजुअल स्टूडियो 2015 के लिए माइक्रोसॉफ्ट ने एक सीआरटी फ़ंक्शन इनलाइन बनाया। अचानक यह हेडर में था न कि CRT लाइब्रेरी इसलिए लाइब्रेरीज़ जो कि लिंक टाइम पर इसे ढूंढने की उम्मीद करती थीं, अब ऐसा नहीं कर सकती हैं और इस तरह की गलतियाँ हो सकती हैं। नतीजा यह हुआ कि इन पुस्तकालयों को विजुअल स्टूडियो 2015 के साथ पुन: निर्माण की आवश्यकता थी।
यदि आप Windows API का उपयोग करते हैं तो आप लिंक त्रुटियां या अजीब व्यवहार भी प्राप्त कर सकते हैं, लेकिन आप लाइब्रेरी उपयोगकर्ता के लिए अलग-अलग यूनिकोड सेटिंग्स के साथ निर्माण करते हैं। ऐसा इसलिए है क्योंकि विंडोज एपीआई में फ़ंक्शन हैं जो यूनिकोड या एएससीआईआई स्ट्रिंग्स और मैक्रोज़ / डिफाइन का उपयोग करते हैं जो प्रोजेक्ट के यूनिकोड सेटिंग्स के आधार पर स्वचालित रूप से सही प्रकार का उपयोग करते हैं। यदि आप लाइब्रेरी की सीमा के पार एक स्ट्रिंग पास करते हैं जो गलत प्रकार है तो रनटाइम पर चीजें टूट जाती हैं। या आप पा सकते हैं कि कार्यक्रम पहली जगह में लिंक नहीं करता है।
ये चीजें अन्य तृतीय पक्ष पुस्तकालयों (जैसे एक ईगन वेक्टर या जीएसएल मैट्रिक्स) से पुस्तकालय की सीमाओं के पार वस्तुओं / प्रकारों को पारित करने के लिए भी सही हैं। यदि तृतीय पक्ष पुस्तकालय आपके पुस्तकालय को संकलित करने के बीच आपके हेडर को बदल देता है और आपका उपयोगकर्ता उनके कोड को संकलित करता है तो चीजें टूट जाएंगी।
मूल रूप से सुरक्षित होने के लिए केवल वही चीजें जो आप लाइब्रेरी सीमाओं के पार कर सकते हैं, वे प्रकारों और सादे पुराने डेटा (POD) में निर्मित हैं। आदर्श रूप से कोई भी पीओडी उन संरचनाओं में होना चाहिए जो आपके स्वयं के हेडर में परिभाषित हैं और किसी तीसरे पक्ष के हेडर पर निर्भर नहीं हैं।
यदि आप केवल हेडर प्रदान करते हैं, तो सभी कोड समान संकलक सेटिंग्स के साथ संकलित हो जाते हैं और एक ही हेडर के खिलाफ होते हैं, तो इनमें से बहुत सारी समस्याएं दूर हो जाती हैं (तीसरे आंशिक पुस्तकालयों के संस्करण प्रदान करना जो आपके और आपके उपयोगकर्ता उपयोग एपीआई संगत हैं)।
हालांकि ऐसे नकारात्मक हैं जो ऊपर उल्लेख किए गए हैं, जैसे कि संकलन का समय। इसके अलावा, आप एक व्यवसाय चला रहे हैं ताकि आप अपने सभी उपयोगकर्ताओं को चोरी करने के मामले में अपने सभी स्रोत कोड कार्यान्वयन विवरण अपने सभी उपयोगकर्ताओं को सौंपना न चाहें।
मुख्य "लाभ" यह है कि इसके लिए आपको स्रोत कोड देने की आवश्यकता होती है, इसलिए आप मशीनों पर त्रुटि रिपोर्ट और उन कंपाइलरों के साथ समाप्त हो जाएंगे जिनके बारे में आपने कभी नहीं सुना है। जब लाइब्रेरी पूरी तरह से टेम्प्लेट होती है, तो आपके पास ज्यादा विकल्प नहीं होते हैं, लेकिन जब आपके पास विकल्प होता है, तो हेडर आमतौर पर केवल एक खराब इंजीनियरिंग पसंद होता है। (दूसरी ओर, बेशक, हेडर का अर्थ केवल यह है कि आपको किसी एकीकरण प्रक्रिया का दस्तावेजीकरण नहीं करना है।)
लिंक टाइम ऑप्टिमाइजेशन (LTO) द्वारा इनलाइनिंग की जा सकती है
मैं इसे हाइलाइट करना चाहता हूं क्योंकि यह हेडर के दो मुख्य लाभों में से केवल एक पुस्तकालयों के मूल्य को कम करता है: "आपको इनलाइन पर हेडर की परिभाषाएं चाहिए"।
इसका एक न्यूनतम ठोस उदाहरण यहां दिखाया गया है: लिंक-टाइम ऑप्टिमाइज़ेशन और इनलाइन
तो आप बस एक ध्वज को पास करते हैं, और बिना किसी रिफैक्टिंग कार्य के बिना ऑब्जेक्ट फ़ाइलों में इनलाइनिंग की जा सकती है, इसके लिए अब हेडर में परिभाषा रखने की कोई आवश्यकता नहीं है।
LTO का अपना डाउनसाइड भी हो सकता है: क्या कोई कारण है कि लिंक-टाइम ऑप्टिमाइज़ेशन (LTO) का उपयोग नहीं किया जाता है?