2015-11-04 8 views
5

मुझे पता है कि जब हम किसी फ़ंक्शन के नाम को मान के रूप में उपयोग करते हैं, तो फ़ंक्शन स्वचालित रूप से एक पॉइंटर में परिवर्तित हो जाता है। निम्नलिखित कोड को देखो:फंक्शन पॉइंटर असाइनमेंट और सी ++ में कॉल करें?

int print(int a) 
{ 
    return a; 
} 

int main() 
{ 
    int (*p)(int) = print; 
    int (*q)(int) = &print; 

    cout << p(8) << endl; 
    cout << (*p)(8) << endl; 
} 

क्यों int (*p)(int) = print; हैं, प्रिंट एक सूचक है, और int (*p)(int) = &print;, & प्रिंट एक सूचक के लिए एक भाषण, बराबर है?

दूसरी ओर, जब हम फ़ंक्शन को कॉल करने के लिए किसी फ़ंक्शन में पॉइंटर का उपयोग करते हैं, तो p(8) और (*p)(8) समकक्ष क्यों हैं?

+0

मैं इसे लगता है कि सिर्फ सुविधा के लिए है , फ़ंक्शन को कॉल करने के लिए उन्हें उपयोग करते समय आपको फ़ंक्शन पॉइंटर्स को स्पष्ट रूप से अव्यवस्थित करना होगा। यदि आप 'typedefs' का उपयोग करते हैं तो आप किसी भी' * 'का उपयोग किए बिना फ़ंक्शन पॉइंटर के साथ काम कर सकते हैं, जो इमो बहुत अच्छा है – user463035818

+2

संभावित डुप्लिकेट [फ़ंक्शन पॉइंटर का डिफ्रेंसिंग कैसे होता है?] (Http://stackoverflow.com/questions/2795575/कैसे-करता-एक-फ़ंक्शन-पॉइंटर-होता है) –

+0

@ सिमोनक्रैमर धन्यवाद। लेकिन लिंक केवल उन्मूलन की व्याख्या करता है, मेरे प्रश्न में फ़ंक्शन पॉइंटर का असाइनमेंट भी शामिल है। – sydridgm

उत्तर

2

print एक समारोह है, लेकिन यह परोक्ष एक समारोह सूचक प्रकार के लिए परिवर्तनीय है। cppref से उद्धरित:

समारोह
सूचक को समारोह प्रकार टी का एक lvalue परोक्ष कि कार्य करने के लिए एक prvalue सूचक के लिए परिवर्तित किया जा सकता है। यह गैर-स्थैतिक सदस्य फ़ंक्शंस पर लागू नहीं होता है क्योंकि गैर-स्थैतिक सदस्य फ़ंक्शंस का उल्लेख करने वाले अंतराल मौजूद नहीं हैं।

तो, आपके मामले में:

int (*p)(int) = print; // Conversion happens. 
int (*q)(int) = &print; // Conversion does not happen. 

स्वचालित रूप में अंतर्निहित रूपांतरण किक जब यह कार्यक्रम संकलन करने के लिए की जरूरत है, और नहीं तो लागू नहीं होता।

फ़ंक्शन कॉलिंग के संबंध में, यह अंतर्निहित फ़ंक्शन कॉल ऑपरेटर () के बारे में है। cppref के अनुसार, अंतर्निहित फ़ंक्शन कॉल ऑपरेटर एक लेल्यू अभिव्यक्ति दोनों पर लागू होता है जो फ़ंक्शन को संदर्भित करता है और कार्य करने के लिए सूचक होता है।

p(8); // The function call operator is applied to a pointer to function. 
(*p)(8); // The function call operator is applied to an lvalue reference to function. 

आपके संदर्भ के लिए (जोर मेरा):

निर्मित समारोह कॉल ऑपरेटर
एक समारोह कॉल अभिव्यक्ति, इस तरह के ई (A1, A2, A3) के रूप में अपने मामले में , अभिव्यक्ति के होते हैं जो फ़ंक्शन, ई का नाम देता है, जिसके बाद संभवतः अभिव्यक्तियों की सूची ए 1, ए 2, ए 3, ... कोष्ठक में सूचीबद्ध करती है।अभिव्यक्ति कि नामों समारोह हो सकता है

क) lvalue अभिव्यक्ति है कि एक समारोह को संदर्भित करता है
ख) सूचक कार्य करने के लिए
...

3

print एक सूचक नहीं है। इसका प्रकार int(int) है, int(*)(int) नहीं है। इस तरह के अंतर प्रकार कटौती सरणियों को

auto& f = print; //type of f is int(&)(int), not int(*(&))(int) 
template<typename Func> 
foo(Func& f); 
foo(print); //Func is deduced to be int(int), not int(*)(int) 

अनुरूप में विशेष रूप से महत्वपूर्ण है, तो आप एक समारोह कॉपी नहीं कर सकते "मूल्य से", लेकिन आप अपने पते के आस-पास कर सकते हैं। उदाहरण के लिए,

int arr[4];  //the type of arr is int[4], not int* 
int *a = arr; //automatic array-to-pointer decay 
int (*a)[4] = &arr; //type match 
int (*p)(int) = print; //automatic function-to-pointer decay 
int (*p)(int) = &print; //type match 

अब जब आप printp के माध्यम से कहते हैं,

p(8)  //automatic dereferencing of p 
(*p)(8) //manual dereferencing of p 
+0

आपका उत्तर कुछ समझ में आता है। लेकिन पुस्तक में ** सी ++ प्राइमर 5 वें संस्करण ** और कई अन्य वेबसाइट ट्यूटोरियल ने फ़ंक्शन नाम का उपयोग करके कहा कि रैवल्यू इसे एक पॉइंटर में परिवर्तित कर देगा। इसलिए मुझे नहीं पता कि आपका उत्तर फ़ंक्शन पॉइंटर असाइनमेंट के लिए एक विशेष स्थिति है या नहीं। – sydridgm

+0

@sydridgm वे सही हैं। और वे मेरे जवाब में फ़ंक्शन-टू-पॉइंटर क्षय का जिक्र कर रहे हैं। – downhillFromHere

संबंधित मुद्दे