आगे की घोषणा बनाम शामिल हैं


18

Reduce the number of #include files in header files. It will reduce build times. Instead, put include files in source code files and use forward declarations in header files.

मैंने इसमें यहाँ पढ़ा। http://www.yolinux.com/TUTORIALS/LinuxTutorialC+CodingStyle.html

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

प्रश्न: यदि हेडर में वर्ग (ए) वर्ग विशेष वर्ग (वर्ग बी) की वास्तविक परिभाषा का उपयोग नहीं करता है, तो आगे की घोषणा कैसे संकलन समय को कम करने में मदद करती है?

जवाबों:


12

कंपाइलर को परवाह नहीं है यदि क्लास ए क्लास बी का उपयोग करता है। यह केवल यह जानता है कि क्लास ए कब संकलित है और इसमें क्लास बी (आगे की घोषणा या अन्यथा) की कोई पूर्व घोषणा नहीं है, यह पैनिक करता है और इसे त्रुटि के रूप में चिह्नित करता है।

यहां जो महत्वपूर्ण है वह यह है कि कंपाइलर जानता है कि आपने अपने कीबोर्ड पर चलने के बाद किसी प्रोग्राम को संकलित करने की कोशिश नहीं की और कुछ रैंडम अक्षर बनाए जो कक्षा के रूप में व्याख्यायित हो सकते हैं या नहीं भी।

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

संपादित करें : इस नियम का अपवाद पूर्वगामी हेडर है। इस मामले में, सभी हेडर संकलित किए जाते हैं और भविष्य के संकलन के लिए सहेजे जाते हैं। यदि हेडर नहीं बदलते हैं, तो कंपाइलर पिछले कंपाइल से प्री-कंपाइल किए गए हेडर का उपयोग स्मार्ट तरीके से कर सकता है और इस प्रकार कंपाइल टाइम को घटा सकता है, लेकिन यह केवल तभी अच्छा काम करता है जब आपको हेडर को बदलने की आवश्यकता न हो।


विवरण के लिए आपका धन्यवाद। उसके बाद ठीक उदाहरण के रूप में आपको लगता है तीन हेडर फाइल देखते हैं vehicle.h, bus.h, toybus.hvehicle.hद्वारा शामिल करें bus.hऔर द्वारा bus.hशामिल करें toybus.h। इसलिए अगर मैं इसमें कुछ बदलाव करता हूं bus.h। संकलक खुला और vehicle.hफिर से पार्स करता है ? क्या यह इसे फिर से संकलित करता है?
नयना आदसूरिया

1
@NayanaAdassuriya हाँ, यह शामिल है और हर बार पार्स किया जाता है, यही वजह है कि आप ऐसी फ़ाइलों को कई बार शामिल होने से रोकने के लिए या (या ifndef के मामले में कम से कम कई बार उपयोग किए जा रहे) को रोकने के लिए हेडर फ़ाइलों में घोषणाएँ देखते #pragma onceया #ifndef __VEHICLE_H_टाइप करते हैं ।
नील

4

क्योंकि तब A.hpp को B.inc को # बंद करने की आवश्यकता नहीं होती है

तो ए। एप्प बन जाता है

class B;//or however forward decl works for classes

class A
{
    B* bInstance_;
//...
}

इसलिए जब ए.एच.पी. शामिल होता है, तब बी.एच.पी. निहित नहीं होता है और सभी फाइलें जो केवल ए.एच.पी. पर निर्भर होती हैं, उन्हें हर बार b.hpp में परिवर्तन करने की आवश्यकता नहीं होती है।


लेकिन स्रोत फ़ाइल (A.cpp) में। वास्तविक हेडर फ़ाइल (Bh) को शामिल करने की आवश्यकता है। इसलिए हर बार इसे संकलित करने की आवश्यकता है। अंत में दोनों तरह के बदलावों के साथ भ की आवश्यकता है। कोई अलग?
नयना आदसूरिया

@NayanaAdassuriya नहीं क्योंकि A केवल B के लिए एक सूचक का उपयोग करता है और B में परिवर्तन A.hpp (या इसमें शामिल फ़ाइलें) को प्रभावित नहीं करेगा
शाफ़्ट फ्रीक

@NayanaAdassuriya: हाँ, A.cpp को recompile करना होगा (यदि यह A के तरीकों के अंदर B की परिभाषा का उपयोग करता है, लेकिन यह आमतौर पर करता है), लेकिन C.cpp, जो A का उपयोग करता है, लेकिन सीधे B का उपयोग नहीं करेगा।
जनवरी हडेक

3

याद रखें, C / C ++ प्रीप्रोसेसर एक अलग, विशुद्ध रूप से टेक्सुअल, प्रोसेसिंग स्टेप है। #includeशामिल हैडर की सामग्री में निर्देश खींचतान और संकलक यह पार्स करने के लिए है। इसके अलावा, प्रत्येक .cppका संकलन पूरी तरह से अलग है, इसलिए यह B.hसंकलन संकलित करते समय संकलक B.cppको कम से कम तब मदद मिलती है जब उसे संकलन करते समय फिर से इसकी आवश्यकता होती है A.cpp। और फिर से संकलन करते समय C.cpp। और D.cpp। और इसी तरह। और उन फ़ाइलों में से प्रत्येक को फिर से संकलित करना होगा यदि इसमें शामिल किसी भी फ़ाइल को बदल दिया गया है।

तो कहते हैं कि वर्ग Aका उपयोग करता है वर्ग Bऔर वर्गों Cऔर Dउपयोग वर्ग Aहै, लेकिन में हेरफेर करने की जरूरत नहीं है B। यदि कक्षा Aको केवल आगे की घोषणा के साथ घोषित किया जा सकता है B, की तुलना B.hमें दो बार संकलित किया जाता है: जब संकलन B.cppऔर A.cpp(क्योंकि Bअभी भी A'तरीकों के अंदर की जरूरत है )।

लेकिन जब A.hभी शामिल है B.h, यह संकलित किया गया है चार बार-जब संकलन B.cpp, A.cpp, C.cppऔर D.cppबाद में दो अब परोक्ष रूप से शामिल हैं के रूप में B.hभी।

इसके अलावा जब हेडर को एक से अधिक बार शामिल किया जाता है, तो प्रीप्रोसेसर को इसे हर बार पढ़ना होता है । यह गार्डिंग #ifdefएस के कारण इसकी सामग्री को संसाधित करना छोड़ देगा , लेकिन यह अभी भी इसे पढ़ता है और गार्ड के अंत की खोज करने की आवश्यकता है, जिसका अर्थ है कि इसे अंदर सभी पूर्वप्रक्रमक निर्देशों को पार्स करना है।

(जैसा कि अन्य उत्तर में उल्लेख किया गया है, पहले से तैयार हेडर इस के इर्द-गिर्द काम करने का प्रयास करते हैं, लेकिन वे कीड़े की अपनी इच्छा है; मूल रूप से आप सिस्टम हेडर के लिए उनका यथोचित उपयोग कर सकते हैं और केवल तब जब आप उनमें से बहुत से उपयोग नहीं कर रहे हों, लेकिन नहीं आपके प्रोजेक्ट में हेडर)


+1, हेडर-शामिल केवल एक गंभीर समस्या बन जाती है जब आपके पास बहुत बड़ी संख्या में कक्षाएं होती हैं, न कि केवल दो कक्षाएं ए और बी होने पर अन्य सभी पोस्ट उस केंद्रीय बिंदु को याद करते हैं।
डॉक ब्राउन

2

एक अग्रगामी घोषणा पूरे हेडर फ़ाइल की तुलना में पार्स करने के लिए बहुत तेज है जिसमें स्वयं और भी अधिक हेडर फाइलें शामिल हो सकती हैं।

इसके अलावा, यदि आप क्लास बी के हेडर फ़ाइल में कुछ बदलते हैं, तो उस हेडर सहित सब कुछ को फिर से तैयार करना होगा। एक आगे की घोषणा के साथ, यह केवल स्रोत फ़ाइल हो सकती है जहां ए का कार्यान्वयन अंदर रहता है। लेकिन अगर ए के हेडर में वास्तव में बी के हेडर शामिल हैं, तो इसमें शामिल सभी चीज़ों a.hppको भी पुन: संयोजित किया जाएगा, भले ही यह बी का कुछ भी उपयोग न करे।

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