फंक्शन पॉइंटर

एक फ़ंक्शन पॉइंटर, जिसे सबरूटीन पॉइंटर या प्रोसेस पॉइंटर भी कहा जाता है, एक सूचक (कंप्यूटर प्रोग्रामिंग) है जो किसी फ़ंक्शन को इंगित करता है। डेटा मान को संदर्भित करने के विरोध में, फ़ंक्शन पॉइंटर स्मृति के भीतर निष्पादन योग्य कोड को इंगित करता है। डेरेफरेंस ऑपरेटर फ़ंक्शन पॉइंटर संदर्भित सबरूटीन उत्पन्न करता है, जिसे सामान्य फ़ंक्शन कॉल की तरह ही लागू किया जा सकता है और तर्क पारित किया जा सकता है। इस तरह के आह्वान को एक अप्रत्यक्ष कॉल के रूप में भी जाना जाता है, क्योंकि एक निश्चित पहचानकर्ता या पते के माध्यम से 'सीधे' के बजाय एक चर के माध्यम से 'अप्रत्यक्ष रूप से' फ़ंक्शन का आह्वान किया जा रहा है।

फ़ंक्शन पॉइंटर्स का उपयोग रन-टाइम मानों के आधार पर निष्पादित करने के लिए फ़ंक्शन का चयन करने का एक आसान तरीका प्रदान करके कोड को सरल बनाने के लिए किया जा सकता है।

फंक्शन पॉइंटर्स तीसरी पीढ़ी की [[प्रोग्रामिंग भाषा]] द्वारा समर्थित हैं | तीसरी पीढ़ी की प्रोग्रामिंग भाषाएँ (जैसे PL/I, COBOL, फोरट्रान, dBASE dBL, और C (प्रोग्रामिंग लैंग्वेज)) और ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग लैंग्वेज (जैसे C ++, C Sharp (प्रोग्रामिंग लैंग्वेज) | C #, और D (प्रोग्रामिंग लैंग्वेज))।

सरल फ़ंक्शन पॉइंटर्स
एक फ़ंक्शन (या सबरूटीन) सूचक का सरलतम कार्यान्वयन एक चर (कंप्यूटर विज्ञान) के रूप में होता है जिसमें निष्पादन योग्य मेमोरी के भीतर फ़ंक्शन का मेमोरी पता होता है। पुरानी तीसरी पीढ़ी की प्रोग्रामिंग भाषा | तीसरी पीढ़ी की भाषाएँ जैसे PL/I और COBOL, साथ ही अधिक आधुनिक भाषाएँ जैसे पास्कल (प्रोग्रामिंग भाषा) और C (प्रोग्रामिंग भाषा) आम तौर पर इस तरह से फ़ंक्शन पॉइंटर्स को लागू करती हैं।

सी
में उदाहरण

निम्नलिखित सी प्रोग्राम दो फ़ंक्शन पॉइंटर्स के उपयोग को दिखाता है:
 * func1 एक डबल-सटीक (डबल) पैरामीटर लेता है और दूसरा डबल देता है, और एक फ़ंक्शन को असाइन किया जाता है जो सेंटीमीटर को इंच में परिवर्तित करता है।
 * func2 एक निरंतर वर्ण सरणी के साथ-साथ एक पूर्णांक के लिए एक सूचक लेता है और एक वर्ण को एक सूचक देता है, और एक C स्ट्रिंग हैंडलिंग फ़ंक्शन को सौंपा जाता है जो किसी वर्ण सरणी में दिए गए वर्ण की पहली घटना के लिए एक सूचक देता है।

<वाक्यविन्यास प्रकाश लैंग = सी>
 * 1) include  /* प्रिंटफ के लिए */
 * 2) include  /* strchr के लिए */

डबल सेमी_टू_इंच (डबल सेमी) { वापसी सेमी / 2.54; }

// strchr सी स्ट्रिंग हैंडलिंग का हिस्सा है (यानी, घोषणा की कोई आवश्यकता नहीं है) // https://en.wikipedia.org/wiki/C_string_handling#Functions देखें

पूर्णांक मुख्य (शून्य) { डबल (*func1)(डबल) = cm_to_inches; चार * (* func2) (स्थिरांक चार *, int) = strchr; प्रिंटफ (% f% s, func1 (15.0), func2 (विकिपीडिया, 'पी')); /* 5.905512 पीडिया प्रिंट करता है */ वापसी 0; } 

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

<वाक्यविन्यास लैंग = सी लाइन = 1>
 * 1) शामिल <गणित.एच>
 * 2) शामिल 

// फंक्शन एक तर्क के रूप में एक फ़ंक्शन पॉइंटर लेता है डबल कंप्यूट_सम (डबल (* funcp) (डबल), डबल लो, डबल हाय) { दोहरा योग = 0.0;

// पॉइंट-टू-फ़ंक्शन '*funcp' द्वारा लौटाए गए मान जोड़ें int मैं; के लिए (i = 0; i <= 100; i++) { // फ़ंक्शन का आह्वान करने के लिए फ़ंक्शन पॉइंटर 'funcp' का उपयोग करें डबल एक्स = आई / 100.0 * (हाय - लो) + लो; डबल वाई = funcp (एक्स); योग + = वाई; }   वापसी राशि / 101.0 * (हाय - लो); }

डबल स्क्वायर (डबल एक्स) { वापसी एक्स * एक्स; }

पूर्णांक मुख्य (शून्य) { दोहरी राशि;

// पॉइंट-टू-फ़ंक्शन के रूप में मानक लाइब्रेरी फ़ंक्शन 'sin ' का उपयोग करें योग = कंप्यूट_सम (पाप, 0.0, 1.0); प्रिंटफ (योग (पाप):% जी \ n, योग);

// पॉइंट-टू-फ़ंक्शन के रूप में मानक लाइब्रेरी फ़ंक्शन 'cos ' का उपयोग करें योग = कंप्यूट_सम (कॉस, 0.0, 1.0); प्रिंटफ (योग (cos):% g \ n, योग);

// यूजर-डिफ़ाइंड फ़ंक्शन 'स्क्वायर ' को पॉइंट-टू-फ़ंक्शन के रूप में उपयोग करें योग = कंप्यूट_सम (वर्ग, 0.0, 1.0); प्रिंटफ (योग (वर्ग):% जी \ n, योग);

वापसी 0; } 

फंक्टर्स
फ़ंक्टर, या फ़ंक्शन ऑब्जेक्ट, फ़ंक्शन पॉइंटर्स के समान हैं, और समान तरीकों से उपयोग किए जा सकते हैं। एक फ़ंक्टर एक वर्ग प्रकार का एक ऑब्जेक्ट है जो फ़ंक्शन-कॉल ऑपरेटर को लागू करता है, ऑब्जेक्ट को फ़ंक्शन कॉल के समान सिंटैक्स का उपयोग करके एक्सप्रेशन के भीतर उपयोग करने की अनुमति देता है। फ़ंक्टर साधारण फ़ंक्शन पॉइंटर्स की तुलना में अधिक शक्तिशाली होते हैं, अपने स्वयं के डेटा मान रखने में सक्षम होते हैं, और प्रोग्रामर को क्लोजर (कंप्यूटर प्रोग्रामिंग) का अनुकरण करने की अनुमति देते हैं। कॉलबैक फ़ंक्शन के रूप में सदस्य फ़ंक्शन का उपयोग करना आवश्यक होने पर उन्हें कॉलबैक फ़ंक्शन के रूप में भी उपयोग किया जाता है। कई शुद्ध वस्तु-उन्मुख भाषाएँ फ़ंक्शन पॉइंटर्स का समर्थन नहीं करती हैं। इस तरह की भाषाओं में कुछ समान लागू किया जा सकता है, हालांकि, प्रोटोकॉल (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) के संदर्भ (कंप्यूटर विज्ञान) का उपयोग करके जो एकल विधि (कंप्यूटर प्रोग्रामिंग) (सदस्य फ़ंक्शन) को परिभाषित करता है। सीएलआई भाषाओं की सूची जैसे कि सी शार्प (प्रोग्रामिंग लैंग्वेज)|सी# और विज़ुअल बेसिक .NET इम्प्लीमेंट प्रकार की सुरक्षा|टाइप-सेफ फंक्शन पॉइंटर्स विद डेलिगेट (सीएलआई)।

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

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

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

सी ++
में C++ में, C में उपयोग की जाने वाली विधि के अलावा, C++ मानक लाइब्रेरी क्लास टेम्पलेट का उपयोग करना भी संभव है std::function, जिनमें से उदाहरण फ़ंक्शन ऑब्जेक्ट हैं:

<वाक्यविन्यास लैंग = सीपीपी>
 * 1) शामिल
 * 2) शामिल <कार्यात्मक>

स्टेटिक डबल डेरिवेटिव (स्थिरांक एसटीडी :: फ़ंक्शन <डबल (डबल)> और एफ, डबल एक्स 0, डबल ईपीएस) { डबल ईपीएस2 = ईपीएस / 2; डबल लो = x0 - ईपीएस 2; डबल हाई = x0 + ईपीएस2; रिटर्न (एफ(हाय) - एफ(लो)) / ईपीएस; }

स्टेटिक डबल एफ (डबल एक्स) { वापसी एक्स * एक्स; }

मुख्य प्रवेश बिंदु { डबल एक्स = 1; std::cout << d/dx(x ^ 2) [@ x = << x << ] = << व्युत्पन्न (f, x, 1e-5) << std::endl; वापसी 0; } 

सी ++
में सदस्य कार्यों के लिए पॉइंटर्स

कक्षाओं या स्ट्रक्चर्स के सदस्य कार्यों से निपटने के दौरान सी ++ फ़ंक्शन पॉइंटर्स का उपयोग करता है। इन्हें ऑब्जेक्ट पॉइंटर या इस कॉल का उपयोग करके बुलाया जाता है। वे इस प्रकार सुरक्षित हैं कि आप उस प्रकार के सूचक का उपयोग करके केवल उस वर्ग (या डेरिवेटिव) के सदस्यों को कॉल कर सकते हैं। यह उदाहरण सादगी के लिए जोड़े गए सदस्य फ़ंक्शन के सूचक के लिए टाइपपीफ के उपयोग को भी प्रदर्शित करता है। स्थैतिक सदस्य कार्यों के लिए फ़ंक्शन पॉइंटर्स पारंपरिक 'सी' शैली में किए जाते हैं क्योंकि इस कॉल के लिए कोई ऑब्जेक्ट पॉइंटर आवश्यक नहीं है।

<वाक्यविन्यास लैंग = सीपीपी> नेमस्पेस एसटीडी का उपयोग करना;
 * 1) शामिल

कक्षा फू {

जनता: इंट ऐड (इंट आई, इंट जे) { वापसी मैं + जे; }   इंट मल्टी (इंट आई, इंट जे) { वापसी आई * जे; }   स्टेटिक इंट नेगेट (इंट आई) { वापसी -मैं; } };

int bar1 (int i, int j, Foo* pFoo, int(Foo::*pfn)(int,int)) { वापसी (पीएफयू -> * पीएफएन) (आई, जे); }

टाइपपीफ इंट (फू :: * फू_पीएफएन) (इंट, इंट);

int bar2(int i, int j, Foo* pFoo, Foo_pfn pfn) { वापसी (पीएफयू -> * पीएफएन) (आई, जे); }

टाइपपीफ इंट (* पीएफएन) (इंट);

इंट बार3(इंट आई, पीएफएन पीएफएन) { रिटर्न पीएफएन (आई); }

मुख्य प्रवेश बिंदु { फू फू; cout << Foo::add(2,4) = << bar1(2,4, &foo, &Foo::add) << endl; cout << Foo::mult(3,5) = << bar2(3,5, &foo, &Foo::mult) << endl; cout << Foo::negate(6) = << bar3(6, &Foo::negate) << endl; वापसी 0; } 

वैकल्पिक सी और सी ++ सिंटैक्स
ऊपर दिया गया C और C++ सिंटैक्स सभी पाठ्य पुस्तकों में उपयोग किया जाने वाला विहित सिंटैक्स है - लेकिन इसे पढ़ना और समझाना मुश्किल है। ऊपर वाला भी  उदाहरण इस सिंटैक्स का उपयोग करते हैं। हालांकि, प्रत्येक सी और सी ++ कंपाइलर फ़ंक्शन पॉइंटर्स घोषित करने के लिए एक और स्पष्ट और संक्षिप्त तंत्र का समर्थन करता है: उपयोग करें , लेकिन सूचक को परिभाषा के हिस्से के रूप में संग्रहीत न करें। ध्यान दें कि इस तरह का एकमात्र तरीका   वास्तव में एक पॉइंटर के साथ इस्तेमाल किया जा सकता है - लेकिन यह इसके पॉइंटर-नेस को हाइलाइट करता है।

सी और सी ++
<वाक्यविन्यास लैंग = सी> // यह 'एफ' की घोषणा करता है, एक ऐसा कार्य जो 'चार' को स्वीकार करता है और 'इंट' लौटाता है। परिभाषा कहीं और है। इंट एफ (चार सी);

// यह 'एफएन' को परिभाषित करता है, एक प्रकार का फ़ंक्शन जो 'चार' स्वीकार करता है और 'इंट' देता है। टाइपपीफ इंट एफएन (चार सी);

// यह 'एफएन' को परिभाषित करता है, टाइप पॉइंटर-टू-'एफएन' का एक चर, और इसे 'एफ' का पता निर्दिष्ट करता है। एफएन *एफएन = और एफ; // नोट 'और' की आवश्यकता नहीं है - लेकिन यह हाइलाइट करता है कि क्या किया जा रहा है।

// यह 'fn' का उपयोग करके 'F' को कॉल करता है, परिणाम को 'a' चर के लिए निर्दिष्ट करता है इंट ए = एफएन ('ए');

// यह 'कॉल' को परिभाषित करता है, एक ऐसा फ़ंक्शन जो पॉइंटर-टू-'एफएन' स्वीकार करता है, इसे कॉल करता है, और परिणाम देता है इंट कॉल (एफएन * एफएन, चार सी) { वापसी एफएन (सी); } // कॉल (एफएन, सी)

// यह 'कॉल' फ़ंक्शन को कॉल करता है, 'एफ' में गुजरता है और परिणाम को 'कॉल' में निर्दिष्ट करता है इंट कॉल = कॉल (और एफ, 'ए'); // फिर से, '&' की आवश्यकता नहीं है

// विरासत: ध्यान दें कि मौजूदा कोड आधारों को बनाए रखने के लिए, उपरोक्त परिभाषा शैली का अभी भी पहले उपयोग किया जा सकता है; // तो नई शैली का उपयोग करके मूल प्रकार को इसके संदर्भ में परिभाषित किया जा सकता है।

// यह 'पीएफएन' को परिभाषित करता है, एक प्रकार का पॉइंटर-टू-टाइप-एफएन। टाइपपीफ एफएन *पीएफएन;

// 'पीएफएन' का उपयोग 'एफएन *' जहां कहीं भी किया जा सकता है पीएफएन पीएफएन = एफ; int CallP (पीएफएन एफएन, चार सी); 

सी ++
ये उदाहरण उपरोक्त परिभाषाओं का उपयोग करते हैं। विशेष रूप से, ध्यान दें कि उपरोक्त परिभाषा के लिए  पॉइंटर-टू-सदस्य-फ़ंक्शन परिभाषाओं में उपयोग किया जा सकता है: <वाक्यविन्यास लैंग = सीपीपी> // यह 'सी' को परिभाषित करता है, समान स्थिर और सदस्य कार्यों वाला एक वर्ग, // और फिर 'सी' नामक एक उदाहरण बनाता है कक्षा सी { जनता: स्टेटिक इंट स्टेटिक (चार सी); इंट सदस्य (चार सी); } सी; // सी

// यह 'पी' को परिभाषित करता है, 'सी' के लिए एक सूचक है और इसे 'सी' का पता निर्दिष्ट करता है सी * पी = & सी;

// यह 'fn' को पॉइंटर-टू-'स्टेटिक' असाइन करता है। // चूंकि कोई 'यह' नहीं है, 'Fn' सही प्रकार है; और 'fn' का उपयोग ऊपर के रूप में किया जा सकता है। एफएन = और सी :: स्टेटिक;

// यह 'एम' को परिभाषित करता है, एक पॉइंटर-टू-मेंबर-ऑफ-'सी' टाइप 'एफएन' के साथ, // और इसे 'सी :: सदस्य' का पता निर्दिष्ट करता है। // आप इसे सभी पॉइंटर्स की तरह राइट-टू-लेफ्ट पढ़ सकते हैं: // 'एम' 'एफएन' प्रकार के वर्ग 'सी' के सदस्य के लिए सूचक है एफएन सी :: * एम = और सी :: सदस्य;

// यह 'सी' में 'सदस्य' को कॉल करने के लिए 'एम' का उपयोग करता है, परिणाम 'सीए' को निर्दिष्ट करता है int सीए = (सी। * एम) ('ए');

// यह 'पी' में 'सदस्य' को कॉल करने के लिए 'एम' का उपयोग करता है, परिणाम 'पीए' को निर्दिष्ट करता है int pA = (p->*m)('A');

// यह 'रेफरी' को परिभाषित करता है, एक ऐसा फ़ंक्शन जो संदर्भ-से-'सी' स्वीकार करता है, // एक पॉइंटर-टू-मेंबर-ऑफ-'C' टाइप 'Fn', और एक 'char', // फ़ंक्शन को कॉल करें और परिणाम लौटाएं इंट रेफ (सी एंड आर, एफएन सी :: * एम, चार सी) { वापसी (आर। * एम) (सी); } // संदर्भ (आर, एम, सी)

// यह 'Ptr' को परिभाषित करता है, एक ऐसा फंक्शन जो पॉइंटर-टू-'C' को स्वीकार करता है, // एक पॉइंटर-टू-मेंबर-ऑफ-'C' टाइप 'Fn', और एक 'char', // फ़ंक्शन को कॉल करें और परिणाम लौटाएं इंट पीआरटी (सी * पी, एफएन सी :: * एम, चार सी) { वापसी (पी -> * एम) (सी); } // पीआरटी (पी, एम, सी)

// विरासत: ध्यान दें कि मौजूदा कोड आधारों को बनाए रखने के लिए, उपरोक्त परिभाषा शैली का अभी भी पहले उपयोग किया जा सकता है; // तो नई शैली का उपयोग करके मूल प्रकार को इसके संदर्भ में परिभाषित किया जा सकता है।

// यह 'FnC' को परिभाषित करता है, एक प्रकार का पॉइंटर-टू-मेंबर-ऑफ-क्लास-'C' टाइप 'Fn' टाइपपीफ एफएन सी :: * एफएनसी;

// 'FnC' का उपयोग जहाँ कहीं भी 'Fn C::*' कर सकता है, किया जा सकता है एफएनसी एफएनसी = और सी :: सदस्य; इंट रेफपी (सी एंड पी, एफएनसी एम, चार सी); 

यह भी देखें

 * प्रतिनिधिमंडल (कम्प्यूटिंग)
 * फंक्शन ऑब्जेक्ट
 * उच्च-क्रम समारोह
 * प्रक्रियात्मक पैरामीटर
 * क्लोजर (कंप्यूटर प्रोग्रामिंग)
 * बेनामी कार्य

बाहरी संबंध

 * FAQ on Function Pointers, things to avoid with function pointers, some information on using function objects
 * Function Pointer Tutorials, a guide to C/C++ function pointers, callbacks, and function objects (functors)
 * Member Function Pointers and the Fastest Possible C++ Delegates, CodeProject article by Don Clugston
 * Pointer Tutorials, C++ documentation and tutorials
 * C pointers explained a visual guide of pointers in C
 * Secure Function Pointer and Callbacks in Windows Programming, CodeProject article by R. Selvam
 * The C Book, Function Pointers in C by "The C Book"
 * Function Pointers in dBASE dBL, Function Pointer in dBASE dBL

Zeiger (Informatik)