Objective-C में #import और #include में क्या अंतर है?


384

ऑब्जेक्टिव-सी में #import और #include के बीच क्या अंतर हैं और क्या ऐसे समय हैं जहां आपको एक दूसरे पर प्रयोग करना चाहिए? एक पदावनत है?

मैं निम्नलिखित ट्यूटोरियल पढ़ रहा था: http://www.otierney.net/objective-c.html#preamble और #import और #include के बारे में इसका पैराग्राफ खुद को विरोधाभासी लगता है या कम से कम अस्पष्ट है।

जवाबों:


341

#Include के बेहतर संस्करण के रूप में #import निर्देश को Objective-C में जोड़ा गया था। हालांकि, इसमें सुधार हुआ है या नहीं, यह अभी भी बहस का विषय है। #import यह सुनिश्चित करता है कि किसी फ़ाइल को केवल एक बार ही शामिल किया जाए ताकि आपको पुनरावर्ती के साथ कोई समस्या न हो। हालांकि, अधिकांश सभ्य हेडर फाइलें वैसे भी इसके खिलाफ खुद को बचाती हैं, इसलिए यह वास्तव में इतना लाभ नहीं है।

असल में, यह आप पर निर्भर है कि आप किसका उपयोग करना चाहते हैं। मैं ऑब्जेक्टिव-सी चीजों (जैसे क्लास की परिभाषाएँ और इस तरह) और #include standard C सामान जो मुझे चाहिए, उसके लिए #import हेडर देते हैं। उदाहरण के लिए, मेरी एक स्रोत फ़ाइल इस तरह दिख सकती है:

#import <Foundation/Foundation.h>

#include <asl.h>
#include <mach/mach.h>

63
भले ही हेडर फ़ाइलों में गार्ड शामिल हों, अगर आप #include का उपयोग करते हैं, तो संकलन के दौरान अभी भी एक प्रदर्शन हिट है - कंपाइलर को शामिल गार्ड को नोटिस करने के लिए प्रत्येक हेडर फ़ाइल को खोलना होगा।
मैट डिलार्ड

4
हेडर गार्ड एक प्रीप्रोसेसर निर्देश है जो हेडर को केवल स्रोत फ़ाइल में एक बार शामिल करना सुनिश्चित करता है।
जेसन कोको

8
मुझे लगता है कि #import वास्तव में GCC द्वारा एक अतिरिक्त है, न कि ऑब्जेक्टिव-सी द्वारा। जब तक आप GCC (या क्लैंग) के साथ संकलित करते हैं, तब तक आप इसका उपयोग गैर- ObjC भाषाओं में कर सकते हैं
डेव डोंगलांग

33
@dave - #import एक ऑब्जेक्टिव-सी है जिसमें प्रीप्रोसेसर है। जीसीसी केवल सी और सी ++ स्रोत फ़ाइलों में भी इसका समर्थन करता है, हालांकि वे आधिकारिक तौर पर पोर्टेबल, पारंपरिक हेडर गार्ड के पक्ष में सी या सी ++ में इसका उपयोग नहीं करने का सुझाव देते हैं। सभी उद्देश्य-सी प्रीप्रोसेसरों में #import शामिल होना चाहिए।
जेसन कोको

13
एक हेडर गार्ड वह होता है जहाँ आप शीर्ष पर जोड़ते हैं: #ifndef myheader #define myheader ... हेडर कोड के बाद ...#endif
टिम

358

प्रीप्रोसेसर के संबंध में बहुत भ्रम की स्थिति प्रतीत होती है।

कंपाइलर क्या करता है जब वह देखता है #includeकि यह उस लाइन को शामिल की गई फ़ाइलों की सामग्री से बदल देता है, कोई सवाल नहीं पूछा गया।

तो अगर आप a.hइस सामग्री के साथ एक फ़ाइल है :

typedef int my_number;

और b.cइस सामग्री के साथ एक फ़ाइल :

#include "a.h"
#include "a.h"

फ़ाइल b.cको संकलन से पहले प्रीप्रोसेसर द्वारा अनुवादित किया जाएगा

typedef int my_number;
typedef int my_number;

जिसके परिणामस्वरूप एक संकलक त्रुटि होगी, चूंकि प्रकार my_numberदो बार परिभाषित किया गया है। भले ही परिभाषा समान हो लेकिन सी भाषा द्वारा इसकी अनुमति नहीं है।

चूंकि हेडर अक्सर एक से अधिक स्थानों में उपयोग किया जाता है, जिसमें आमतौर पर गार्ड का उपयोग सी में किया जाता है। यह इस तरह दिखता है:

 #ifndef _a_h_included_
 #define _a_h_included_

 typedef int my_number;

 #endif

फ़ाइल में b.cअभी भी हैडर की पूरी सामग्री प्रीप्रोसेस होने के बाद दो बार उसमें होगी। लेकिन दूसरा उदाहरण नजरअंदाज कर दिया जाएगा क्योंकि मैक्रो _a_h_included_पहले से ही परिभाषित किया गया है।

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

ऑब्जेक्टिव-सी में #importप्रीप्रोसेसर इंस्ट्रक्शन है (इसे कुछ कंपाइलर्स और ऑप्शंस के साथ C और C ++ कोड के लिए भी इस्तेमाल किया जा सकता है)। यह लगभग वैसा ही है #include, लेकिन यह आंतरिक रूप से भी नोट करता है कि किस फ़ाइल को पहले ही शामिल किया जा चुका है। #importलाइन केवल पहली बार यह का सामना करना पड़ा है के लिए नामित किया गया फ़ाइल की सामग्री से बदल दिया है। हर बार उसके बाद इसे नजरअंदाज किया जाता है।


4
यह स्वीकार किए जाते हैं की तुलना में बेहतर जवाब है। @Gill, आपको स्वीकृत उत्तर को बदलना चाहिए।
गुयेन मिन्ह बिनह

5
7000 लाइन टेम्पलेट हेडर फ़ाइल पर 4 #includeएस को बदलने के बाद #import, संकलन और एक्सकोड इंटेलीजेंस जवाबदेही में ध्यान देने योग्य प्रदर्शन में सुधार होता है। (मुझे नहीं लगता कि मैं इसकी कल्पना कर रहा हूं)
bobobobo

62

मैं जेसन से सहमत हूं।

मैं ऐसा करते हुए पकड़ा गया:

#import <sys/time.h>  // to use gettimeofday() function
#import <time.h>      // to use time() function

जीएनयू जीसीसी के लिए, यह शिकायत करता रहा कि समय () फ़ंक्शन परिभाषित नहीं था।

तो फिर मैंने #import को #include में बदल दिया और सब ठीक हो गया।

कारण:

आप #import <sys / time.h>:
    <sys / time.h> में #defines का उपयोग करके केवल <time.h> का एक हिस्सा शामिल है

आप #import <time.h>:
    नहीं जाओ। भले ही # time.h> का केवल हिस्सा पहले से ही शामिल था,
    जहां तक ​​#import का संबंध है, वह फ़ाइल अब पहले से ही पूरी तरह से शामिल है।

जमीनी स्तर:

पारंपरिक रूप से C / C ++ हेडर में अन्य के कुछ भाग शामिल हैं फाइलें।
तो C / C ++ हेडर के लिए, #include का उपयोग करें।
Objc / objc ++ हेडर के लिए, #import का उपयोग करें।


1
ऐसा लगता है कि इस क्लैंग में यह परिभाषित समस्या नहीं है।
ओह

23

#includeसी की तरह काम करता है #include

#importइस बात पर नज़र रखता है कि हेडर को पहले ही शामिल किया गया है और इसे अनदेखा किया गया है यदि किसी हेडर को संकलन इकाई में एक से अधिक बार आयात किया जाता है। इससे हेडर गार्ड का उपयोग करना अनावश्यक हो जाता है।

लब्बोलुआब यह है कि बस #importउद्देश्य-सी में उपयोग किया जाता है और चिंता न करें कि आपके हेडर एक से अधिक बार कुछ आयात करते हैं।


2
एक मिनट के लिए दिखावा करना कि मैं C #include से परिचित नहीं हूं (ज्यादातर इसलिए कि मैं नहीं हूं), #include और #import में मुख्य अंतर क्या है? इसके अलावा, क्या आप मुझे बता सकते हैं कि हेडर गार्ड क्या है?
रयान गुइल

@ रेयान: स्वेन के जवाब को देखें।
एड्रियन पेट्रेस्क्यू

13

मुझे पता है कि यह धागा पुराना है ... लेकिन "आधुनिक समय" में .. वहाँ एक बेहतर " क्लैंग के @importमॉड्यूल के माध्यम से रणनीति" शामिल है - जो कि अक्सर अनदेखी की जाती है।

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

@import Darwin; // Like including all of /usr/include. @see /usr/include/module.map

या

@import Foundation;  //  Like #import <Foundation/Foundation.h>
@import ObjectiveC;  //  Like #import <objc/runtime.h>

हालाँकि, यह मॉड्यूल आयात संबंधित #include से काफी भिन्न व्यवहार करता है: जब कंपाइलर मॉड्यूल को ऊपर आयात देखता है, तो यह मॉड्यूल के एक द्विआधारी प्रतिनिधित्व को लोड करता है और इसके एपीआई को सीधे आवेदन के लिए उपलब्ध कराता है। प्रीप्रोसेसर परिभाषाएँ जो आयात घोषणा से पहले एपीआई पर कोई प्रभाव नहीं डालती हैं ... क्योंकि मॉड्यूल स्वयं एक अलग, स्टैंडअलोन मॉड्यूल के रूप में संकलित किया गया था। इसके अतिरिक्त, मॉड्यूल का उपयोग करने के लिए आवश्यक किसी भी लिंकर झंडे को मॉड्यूल आयात किए जाने पर स्वचालित रूप से प्रदान किया जाएगा। यह शब्दार्थ आयात मॉडल प्रीप्रोसेसर समावेश मॉडल की कई समस्याओं को संबोधित करता है।

मॉड्यूल को सक्षम करने के आदेश-पंक्ति ध्वज पारित -fmodulesउर्फ CLANG_ENABLE_MODULESमें Xcode- संकलन समय पर। जैसा कि ऊपर उल्लेख किया गया है .. यह रणनीति किसी भी और सभी को कम करती है LDFLAGS। जैसा कि, आप किसी भी "OTHER_LDFLAGS" सेटिंग्स को हटा सकते हैं, साथ ही किसी भी "लिंकिंग" चरणों को भी।

यहां छवि विवरण दर्ज करें

मुझे बहुत स्नैपर महसूस करने के लिए संकलन / लॉन्च समय मिलता है (या संभवतः, लिंक करते समय बस एक अंतराल से कम है?) .. और, अब एक्स्ट्रासियस प्रोजेक्ट-प्रीफ़िक्स.पिपल फ़ाइल को शुद्ध करने का एक शानदार अवसर प्रदान करता है। निर्माण सेटिंग्स इसी, GCC_INCREASE_PRECOMPILED_HEADER_SHARING, GCC_PRECOMPILE_PREFIX_HEADER, और GCC_PREFIX_HEADER, आदि

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


4

यदि आप C ++ और मैक्रोज़ से परिचित हैं, तो

#import "Class.h" 

के समान है

{
#pragma once

#include "class.h"
}

जिसका मतलब है कि आपकी क्लास केवल एक बार लोड होगी जब आपका ऐप चलेगा।


क्या यह #pragma का एक बार समर्थित उपयोग है? मैं हमेशा pragma होने की जरूरत सोचा अंदर समेत एड काम करने के लिए फ़ाइल।
१०:३५

@uliwitness तुम सही हो। #pragma onceशामिल फ़ाइल में रखा गया है, न कि वह फ़ाइल जिसमें शामिल है। -1 उसके लिए।
हर्ज़ब्यूब

1

हो सकता है .hकि मेरे पास मेरी एक फ़ाइल में एक वैश्विक चर था जो समस्या पैदा कर रहा था, और मैंने इसे इसके externसामने जोड़कर हल किया।


0

यदि आप संकलक की तुलना में .h फ़ाइलों में दो बार # फ़ाइल निकालते हैं, तो त्रुटि होगी। लेकिन अगर आप एक फ़ाइल को एक से अधिक बार कंपाइल करते हैं तो कंपाइलर उसे अनदेखा कर देगा।


8
#includeएक ही फ़ाइल दो बार त्रुटि का परिणाम नहीं है
kennytm

1
@ केनीटीएम की टिप्पणी को पूरक करने के लिए, # एक ही हेडर में एक ही फाइल को दो बार शामिल करें-परिणामस्वरूप सामान्य त्रुटि वाले गॉर्ड (#ifndef FILE_NAME_H #define FILE_NAME_H #end) में त्रुटि नहीं होती है। यह अपेक्षित अभ्यास है। #Import का उपयोग कर हेडर गार्ड की जरूरत नहीं होती है।
jbat100

@ jbat100: #includeबस एक कॉपी-और-पेस्ट तंत्र है। #includeगार्ड, जैसे "X मैक्रो" को शामिल किए बिना एक से अधिक बार जानबूझकर उपयोग किया जाता है ।
kennytm

एक फ़ाइल को दो बार शामिल करने से आप जो भी शामिल करते हैं उसके आधार पर त्रुटियों का परिणाम हो सकता है । मैंने सी कोड देखा है जो #includeएक प्रकार के टेम्प्लेट को लागू करने के लिए उपयोग किया जाता है। उन्होंने एक किया #define, जिसमें एक हेडर शामिल था , #undefडी और रेडी #define, एक ही हेडर को दूसरी बार शामिल किया। इसके परिणामस्वरूप कोड को मानकीकृत, मान्य और दो बार शामिल किया गया, क्योंकि परिभाषित का मूल्य अलग था। इसलिए उपयोग करने के फायदे हैं #include, लेकिन यदि आप C ++ या ObjC जैसी आधुनिक भाषा का उपयोग कर रहे हैं, तो आपको आमतौर पर इसकी आवश्यकता नहीं है।
१०:१५ बजे

0

#includeइसका उपयोग किसी अन्य फ़ाइल से "चीजों" को प्राप्त करने के लिए #includeकिया जाता है।

फ़ाइल में: main.cpp

#include "otherfile.h"

// some stuff here using otherfile.h objects,
// functions or classes declared inside

प्रत्येक हेडर फ़ाइल (* .h) के शीर्ष पर हेडर गार्ड का उपयोग किया जाता है ताकि एक ही फाइल को अधिक से अधिक बार रोका जा सके (यदि ऐसा होता है तो आपको संकलन त्रुटियां मिलेंगी)।

फ़ाइल में: otherfile.h

#ifndef OTHERFILE
#define OTHERFILE

// declare functions, classes or objects here

#endif

यहां तक ​​कि अगर आप #includeअपने कोड में "otherfile.h" n समय लगाते हैं, तो इसके अंदर इसे दोबारा नहीं रखा जाएगा।


0
#include + guard == #import

#include guardविकी - मैक्रो गार्ड, हेडर गार्ड या फाइल गार्ड को डबल करने से रोकता है एक हेडर शामिल हैpreprocessorजो एक बिल्ड टाइम को धीमा कर सकता है

अगला कदम है

.pch[के बारे में] =>@import [के बारे में]

[#import in .hया .m]

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