यह सुनिश्चित करना कि हेडर सीपीपी फ़ाइल में स्पष्ट रूप से शामिल हैं


10

मुझे लगता है कि #includeसीपीपी फ़ाइल में उपयोग किए जाने वाले किसी भी प्रकार के हेडर के लिए यह आम तौर पर अच्छा अभ्यास है , भले ही एचपीपी फ़ाइल के माध्यम से पहले से ही शामिल हो। इसलिए मैं #include <string>अपने एचपीपी और सीपीपी दोनों में हो सकता है, उदाहरण के लिए, भले ही मैं अभी भी संकलित कर सकता हूं अगर मैंने इसे सीपीपी में छोड़ दिया। इस तरह मुझे इस बारे में चिंता करने की ज़रूरत नहीं है कि मेरे एचपीपी ने आगे की घोषणा की या नहीं।

क्या कोई उपकरण हैं जो इस #includeकोडिंग शैली को लागू कर सकते हैं? क्या मुझे इस कोडिंग शैली को लागू करना चाहिए ?

चूंकि प्रीप्रोसेसर / कंपाइलर को परवाह नहीं है कि क्या #includeएचपीपी या सीपीपी से आ रहा है, मुझे कोई प्रतिक्रिया नहीं मिलती है अगर मैं इस शैली का पालन करना भूल जाता हूं।

जवाबों:


7

यह उन "कोडों" के बजाय "मानक" प्रकारों में से एक है जो कोडिंग मानकों के अनुसार हैं। इसका कारण यह है कि आपको इसे लागू करने के लिए C ++ पार्सर लिखना बहुत पसंद होगा।

हेडर फ़ाइलों के लिए एक बहुत ही सामान्य नियम यह है कि उन्हें अपने आप खड़ा होना चाहिए। हेडर फ़ाइल की आवश्यकता नहीं होनी चाहिए कि कुछ अन्य हेडर फ़ाइलों को प्रश्न में हेडर शामिल करने से पहले #included किया जाए। यह एक परीक्षण योग्य आवश्यकता है। कुछ यादृच्छिक शीर्षकों को देखते हुए foo.hh, निम्नलिखित को संकलित और चलाना चाहिए:

#include "foo.hh"
int main () {
   return 0;
}

इस नियम के कुछ हेडर में अन्य वर्गों के उपयोग के संबंध में परिणाम हैं। कभी-कभी उन परिणामों को आगे उन अन्य वर्गों की घोषणा करके टाला जा सकता है। यह बहुत सारे मानक पुस्तकालय वर्गों के साथ संभव नहीं है। कोई आगे का रास्ता जैसे एक टेम्पलेट इन्स्टेन्शियशन घोषित करने के लिए है std::stringया std::vector<SomeType>। आपको #includeशीर्षलेख में उन एसटीएल हेडर के पास होना चाहिए, भले ही प्रकार का एकमात्र उपयोग किसी फ़ंक्शन के तर्क के रूप में हो।

एक और समस्या सामान के साथ है जिसे आप संयोग से घसीटते हैं। उदाहरण: निम्नलिखित पर विचार करें:

फ़ाइल foo.cc:

#include "foo.hh"
#include "bar.hh"

void Foo::Foo () : bar() { /* body elided */ }

void Foo::do_something (int item) {
   ...
   bar.add_item (item);
   ...
}

यहाँ barएक वर्ग Fooडेटा सदस्य है जो टाइप का है Bar। आपने यहाँ सही काम किया है और बार-बार # निकाह किया है, भले ही उसे हैडर में शामिल किया गया होगा जो वर्ग को परिभाषित करता है Foo। हालाँकि, आपने उपयोग किए गए सामान को शामिल नहीं किया है Bar::Bar()और Bar::add_item(int)। ऐसे कई मामले हैं जहां इन कॉलों के परिणामस्वरूप अतिरिक्त बाहरी संदर्भ हो सकते हैं।

यदि आप foo.oइस तरह के एक उपकरण के साथ विश्लेषण करते हैं nm, तो यह दिखाई देगा कि फ़ंक्शन foo.ccसभी प्रकार के सामान को कॉल कर रहे हैं जिसके लिए आपने उपयुक्त नहीं किया है #include। तो क्या आपको #includeउन आकस्मिक बाहरी संदर्भों के लिए निर्देश जोड़ना चाहिए foo.cc? जवाब बिल्कुल नहीं है। समस्या यह है कि उन कार्यों को अलग करना बहुत कठिन है जिन्हें संयोग से सीधे कहा जाता है।


2

क्या मुझे इस कोडिंग शैली को लागू करना चाहिए?

शायद ऩही। मेरा नियम यह है: हेडर फ़ाइल समावेशन आदेश निर्भर नहीं हो सकता है।

आप इसे सरल नियम के साथ आसानी से सत्यापित कर सकते हैं कि xc द्वारा शामिल पहली फ़ाइल xh है


1
क्या आप इसे विस्तार से बताएंगे? मैं यह नहीं देख सकता कि वास्तव में आदेश-स्वतंत्रता का सत्यापन कैसे होगा।
detly

1
यह वास्तव में आदेश स्वतंत्रता की गारंटी नहीं देता है - यह सिर्फ यह सुनिश्चित करता है कि #include "x.h"कुछ पूर्ववर्ती की आवश्यकता के बिना काम करेगा #include। यदि आप दुरुपयोग नहीं करते हैं तो यह काफी अच्छा है #define
केविन क्लाइन

1
ओह मैं समझा। फिर भी एक अच्छा विचार है।
detly

2

यदि आपको एक नियम लागू करने की आवश्यकता है जो विशेष हेडर फ़ाइलों को अपने दम पर खड़ा होना चाहिए तो आप उन उपकरणों का उपयोग कर सकते हैं जो आपके पास पहले से हैं। एक मूल मेकफाइल बनाएं जो प्रत्येक हेडर फ़ाइल को व्यक्तिगत रूप से संकलित करता है, लेकिन ऑब्जेक्ट फ़ाइल उत्पन्न नहीं करता है। आप हेडर फ़ाइल को (C या C ++ मोड) संकलित करने के लिए कौन सा मोड निर्दिष्ट कर पाएंगे और यह सत्यापित कर पाएंगे कि यह अपने आप खड़ा हो सकता है। आप उचित अनुमान लगा सकते हैं कि आउटपुट में कोई झूठी सकारात्मकता नहीं है, सभी आवश्यक निर्भरताएं घोषित की गई हैं और आउटपुट सटीक है।

यदि आप एक आईडीई का उपयोग कर रहे हैं, तो आप अभी भी बिना मेकफाइल (आपके आईडीई के आधार पर) के बिना इसे पूरा करने में सक्षम हो सकते हैं। बस एक अतिरिक्त प्रोजेक्ट बनाएं, उस हेडर फ़ाइलों को जोड़ें जिसे आप सत्यापित करना चाहते हैं और इसे C या C ++ फ़ाइल के रूप में संकलित करने के लिए सेटिंग्स बदल सकते हैं। उदाहरण के लिए MSVC में आप "कॉन्फ़िगरेशन गुण-> सामान्य" में "आइटम प्रकार" सेटिंग को बदल देंगे।


1

मुझे नहीं लगता कि ऐसा कोई उपकरण मौजूद है, लेकिन मुझे खुशी होगी अगर कोई अन्य उत्तर मुझे नापसंद हो।

इस तरह के उपकरण को लिखने में समस्या यह है कि यह बहुत आसानी से एक गलत परिणाम की सूचना देता है, इसलिए मुझे लगता है कि ऐसे उपकरण का शुद्ध लाभ शून्य के करीब होना चाहिए।

इस तरह का एक उपकरण काम कर सकता है, यदि यह अपनी प्रतीक तालिका को संसाधित किए गए शीर्ष लेख की सामग्री के लिए बस रीसेट कर सकता है, लेकिन फिर आप इस समस्या में भाग लेते हैं कि किसी पुस्तकालय के बाहरी एपीआई को बनाने वाले शीर्षलेख वास्तविक घोषणाओं को प्रस्तुत करते हैं आंतरिक हेडर।
उदाहरण के लिए, <string>GCC में libc ++ कार्यान्वयन कुछ भी घोषित नहीं करता है, लेकिन इसमें सिर्फ आंतरिक हेडर का एक समूह शामिल है जिसमें वास्तविक घोषणाएं शामिल हैं। यदि उपकरण अपनी प्रतीक तालिका को सिर्फ इस बात के लिए रीसेट करता है कि उसके द्वारा घोषित क्या था <string>, तो वह कुछ भी नहीं होगा।
आप उपकरण के बीच अंतर कर सकते हैं #include ""और #include <>, लेकिन यह मदद नहीं करता है अगर कोई बाहरी पुस्तकालय #include ""एपीआई में अपने आंतरिक हेडर को शामिल करने के लिए उपयोग करता है।


1

यह #Pragma onceहासिल नहीं करता है ? आप किसी भी चीज़ को जितनी बार चाहें शामिल कर सकते हैं, या तो सीधे या जंजीर के माध्यम से शामिल कर सकते हैं, और जब तक #Pragma onceउनमें से प्रत्येक के बगल में है, हेडर केवल एक बार शामिल किया जाता है।

इसे लागू करने के लिए, अच्छी तरह से शायद आप एक बिल्ड सिस्टम बना सकते हैं जिसमें बस प्रत्येक हेडर को कुछ डमी मुख्य फ़ंक्शन के साथ शामिल किया जाए, बस यह सुनिश्चित करने के लिए। #ifdefश्रृंखला में परीक्षण के उस तरीके के साथ सर्वोत्तम परिणाम शामिल हैं।


1

हमेशा सीपीपी फाइल में हेडर फाइल शामिल करें। यह न केवल संकलित समय को काफी कम करता है, बल्कि अगर आप पहले से तैयार हेडर के साथ जाने का निर्णय लेते हैं, तो यह आपको बहुत परेशानी से बचाता है। मेरे अनुभव में, यहां तक ​​कि आगे की घोषणाओं की परेशानी भी अभ्यास के लायक है। आवश्यक होने पर ही नियम तोड़ें।


क्या आप बता सकते हैं कि यह "संकलन समय को बहुत कम" कैसे करेगा?
मावग का कहना है कि मोनिका

1
यह सुनिश्चित करता है कि प्रत्येक संकलन इकाई (CPP फ़ाइल) केवल संकलन समय पर फ़ाइलों को शामिल करने के न्यूनतम में खींचती है। अन्यथा, यदि आप एच फाइलों में शामिल करते हैं, तो झूठा निर्भरता श्रृंखला जल्दी बनती है, और आप अंत में सभी संकलन के साथ सभी को खींचते हैं।
ग्वोड्डेन

गार्ड्स को शामिल करने के साथ, मैं "महत्त्वपूर्ण" quesiton कर सकता हूं, लेकिन मुझे लगता है कि डिस्क एक्सेस (उन inlcude गॉर्ड्स की खोज करने के लिए सीमारेखा में) "धीमा" है, इसलिए बिंदु को कम करेगा। स्पष्ट करने के लिए धन्यवाद
मावग का कहना है कि मोनिका

0

मैं कहूंगा कि इस अधिवेशन के फायदे और नुकसान दोनों हैं। एक तरफ यह जानना अच्छा है कि आपकी .cpp फ़ाइल क्या है। दूसरी ओर, शामिल की सूची आसानी से हास्यास्पद आकार तक बढ़ सकती है।

इस सम्मेलन को प्रोत्साहित करने का एक तरीका यह है कि आप अपने स्वयं के हेडर में कुछ भी शामिल न करें, लेकिन केवल .cpp फ़ाइलों में। तब आपके हेडर का उपयोग करने वाली कोई भी .cpp फ़ाइल तब तक संकलित नहीं होगी जब तक कि आप स्पष्ट रूप से उस पर निर्भर अन्य सभी शीर्षकों को शामिल नहीं करते हैं।

संभवतः कुछ उचित समझौता यहाँ क्रम में हैं। उदाहरण के लिए, आप यह तय कर सकते हैं कि अपने स्वयं के हेडर के अंदर मानक पुस्तकालय हेडर शामिल करना ठीक है, लेकिन अब और नहीं।


3
यदि आप छोड़ते हैं हेडर से बाहर निकलते हैं, तो शामिल करें आदेश पर बात शुरू होती है ... और मैं निश्चित रूप से इससे बचना चाहता हूं ।
एम। डुडले

1
-1: एक निर्भरता दुःस्वप्न बनाता है।
Xh में

1
@ M.Dudley, जैसा मैंने कहा, फायदे और नुकसान हैं।
दिमा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.