फंक्शन पॉइंट्स का क्या मतलब है?


94

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

क्या आप फंक्शन पॉइंटर्स (C या C ++ में) के अच्छे उपयोग के कुछ उदाहरण दे सकते हैं?


1
आप में काफी समारोह संकेत के बारे में चर्चा का एक सा मिल सकता है इस से संबंधित तो सवाल
इसका 12

20
@itsmatt: वास्तव में नहीं। "टीवी कैसे काम करता है?" "मैं टीवी के साथ क्या करूँ?"
भारतीय स्टेट बैंक

6
C ++ में आप शायद इसके बजाय एक फ़नकार ( en.wikipedia.org/wiki/Function_object#In_C_and_C.2B.2B ) का उपयोग करेंगे।
kennytm

11
पुराने अंधेरे दिनों में जब C ++ को C के लिए "संकलित" किया गया था, तो आप वास्तव में देख सकते हैं कि वर्चुअल तरीके कैसे कार्यान्वित किए जाते हैं - yep, फंक्शनर्स के साथ।
sbk

1
बहुत जरूरी है जब आप C ++ को किसी प्रबंधित C ++ या C # के साथ उपयोग करना चाहते हैं, अर्थात: प्रतिनिधियों और कॉलबैक
Maher

जवाबों:


108

अधिकांश उदाहरण कॉलबैक के लिए उबालते हैं : आप एक फ़ंक्शन f()को किसी अन्य फ़ंक्शन के पते से गुजरते हैं g(), और कुछ विशिष्ट कार्य के लिए f()कॉल g()करते हैं। यदि आप इसके बजाय f()पते को पास करते हैं h(), तो इसके बजाय f()वापस कॉल करेंगे h()

मूल रूप से, यह एक फ़ंक्शन को पैरामीरिज करने का एक तरीका है : इसके व्यवहार का कुछ हिस्सा हार्ड-कोडेड नहीं है f(), लेकिन कॉलबैक फ़ंक्शन में है। कॉल f()करने वाले अलग-अलग कॉलबैक फ़ंक्शंस पास करके अलग तरह से व्यवहार कर सकते हैं । एक क्लासिक qsort()सी मानक पुस्तकालय से है जो एक तुलनात्मक फ़ंक्शन के लिए एक सूचक के रूप में अपनी छंटाई मानदंड लेता है।

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

class functor {
  public:
     void operator()(int i) {std::cout << "the answer is: " << i << '\n';}
};

functor f;
f(42);

इसके पीछे विचार यह है कि एक फ़ंक्शन पॉइंटर के विपरीत, एक फ़ंक्शन ऑब्जेक्ट न केवल एक एल्गोरिदम ले जा सकता है, बल्कि डेटा भी:

class functor {
  public:
     functor(const std::string& prompt) : prompt_(prompt) {}
     void operator()(int i) {std::cout << prompt_ << i << '\n';}
  private:
     std::string prompt_;
};

functor f("the answer is: ");
f(42);

एक और लाभ यह है कि फ़ंक्शन पॉइंटर्स के माध्यम से कॉल की तुलना में ऑब्जेक्ट्स को कार्य करने के लिए कभी-कभी इनलाइन कॉल करना आसान होता है। यह एक कारण है कि C ++ में छंटाई कभी-कभी C में छांटने से तेज होती है।


1
+1, इस उत्तर को एक अन्य उदाहरण के लिए भी देखें: stackoverflow.com/questions/1727824/…
शार्प्यूट

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

2
@krynr: वर्चुअल फ़ंक्शंस केवल कंपाइलर कार्यान्वयनकर्ताओं के लिए फ़ंक्शन पॉइंटर्स हैं, और यदि आपको यह पूछना है कि वे किस चीज़ के लिए अच्छे हैं, तो आप संभवतः (उम्मीद है!) एक कंपाइलर के वर्चुअल फ़ंक्शन तंत्र को लागू करने की आवश्यकता नहीं है।
sbi

@ एसएसबी: आप बिल्कुल सही हैं। हालांकि, मुझे लगता है कि यह समझने में मदद करता है कि अमूर्त के अंदर क्या चल रहा है। इसके अलावा, सी में अपने खुद के व्यवहार्य को लागू करना और ऑब्जेक्ट ओरिएंटेड कोड लिखना एक बहुत अच्छा सीखने का अनुभव है।
फ्लोरियन

ब्राउनी ने ओपी द्वारा पूछे गए जीवन, ब्रह्मांड और सब कुछ के साथ उत्तर प्रदान करने के लिए
संकेत दिया

41

खैर, मैं आम तौर पर उन्हें (पेशेवर) जंप टेबल में उपयोग करता हूं ( यह स्टैकऑवरफ्लो प्रश्न भी देखें )।

जंप टेबल सामान्य रूप से (लेकिन विशेष रूप से नहीं) परिमित राज्य मशीनों में उपयोग किए जाते हैं ताकि उन्हें डेटा संचालित किया जा सके। नेस्टेड स्विच / केस के बजाय

  switch (state)
     case A:
       switch (event):
         case e1: ....
         case e2: ....
     case B:
       switch (event):
         case e3: ....
         case e1: ....

आप फ़ंक्शन पॉइंट का 2d सरणी बना सकते हैं और बस कॉल कर सकते हैं handleEvent[state][event]


24

उदाहरण:

  1. कस्टम छँटाई / खोज
  2. विभिन्न पैटर्न (जैसे रणनीति, प्रेक्षक)
  3. कॉलबैक

1
जंप टेबल इसका महत्वपूर्ण उपयोग है।
आशीष

यदि कुछ काम किए गए उदाहरण हैं, तो यह मेरा उत्थान होगा।
डोनल फैलो

1
यदि C ++ उपलब्ध है, तो वर्चुअल फ़ंक्शंस का उपयोग करके रणनीति और प्रेक्षक को बेहतर तरीके से लागू किया जा सकता है। अन्यथा +1।
बिली ओनेल

मुझे लगता है कि फ़ंक्शन पॉइंटर्स का बुद्धिमान उपयोग पर्यवेक्षक को अधिक कॉम्पैक्ट और हल्का वजन बना सकता है
एंड्री

@Billyoneal केवल यदि आप कठोरता से GoF परिभाषा से चिपके रहते हैं, तो इसके साथ Javaism लीक हो रहा है। मैं का वर्णन होगा std::sortकी compपैरामीटर एक रणनीति के रूप में
Caleth

10

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


7

उपरोक्त सभी से सहमत हैं, साथ ही .... जब आप रनिंग के दौरान एक dll को गतिशील रूप से लोड करते हैं, तो आपको फ़ंक्शन को कॉल करने के लिए फ़ंक्शन पॉइंटर्स की आवश्यकता होगी।


1
मैं यह हर समय विंडोज एक्सपी का समर्थन करने के लिए करता हूं और अभी भी विंडोज 7 उपहार का उपयोग करता हूं। +1।
बिली ओनेल

7

मैं यहां करंट के खिलाफ जाने वाला हूं।

सी में, फ़ंक्शन पॉइंटर्स अनुकूलन को लागू करने का एकमात्र तरीका है, क्योंकि कोई ओओ नहीं है।

C ++ में, आप समान परिणाम के लिए फ़ंक्शन पॉइंटर्स या फ़ंक्शनलर्स (फ़ंक्शन ऑब्जेक्ट) का उपयोग कर सकते हैं।

फंक्शनलर्स के पास रॉ फंक्शन पॉइंट्स पर कई फायदे हैं, जो उनकी वस्तु प्रकृति के कारण हैं:

  • वे के कई अधिभार प्रस्तुत कर सकते हैं operator()
  • उनके पास मौजूदा चर के लिए राज्य / संदर्भ हो सकते हैं
  • उन्हें मौके पर बनाया जा सकता है ( lambdaऔर bind)

मैं व्यक्तिगत रूप से फंक्शन पॉइंटर्स (बॉयलरप्लेट कोड के बावजूद) के लिए फंक्शनलर्स पसंद करता हूं, ज्यादातर इसलिए क्योंकि फंक्शन पॉइंटर्स के लिए सिंटैक्स आसानी से बालों ( फंक्शन पॉइंटर ट्यूटोरियल से ) प्राप्त कर सकते हैं :

typedef float(*pt2Func)(float, float);
  // defines a symbol pt2Func, pointer to a (float, float) -> float function

typedef int (TMyClass::*pt2Member)(float, char, char);
  // defines a symbol pt2Member, pointer to a (float, char, char) -> int function
  // belonging to the class TMyClass

केवल समय मैंने कभी फ़ंक्शन पॉइंटर्स का उपयोग किया है, जहां फ़ंक्शंस Boost.Spirit में नहीं हो सकता था। उन्होंने एकल टेम्पलेट पैरामीटर के रूप में मापदंडों की एक मनमानी संख्या पारित करने के लिए वाक्यविन्यास का पूरी तरह से दुरुपयोग किया है।

 typedef SpecialClass<float(float,float)> class_type;

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


सिर्फ इसलिए कि आप अपने फ़ंक्शन को नहीं देखते हैं इसका मतलब यह नहीं है कि आप उनका उपयोग नहीं करते हैं। हर बार (जब तक कंपाइलर इसे दूर ऑप्टिमाइज़ नहीं कर सकता) आप वर्चुअल फ़ंक्शन को कॉल करते हैं, बूस्ट का उपयोग करते हैं bindया functionआप फ़ंक्शन पॉइंटर्स का उपयोग करते हैं। यह कहने जैसा है कि हम C ++ में पॉइंटर्स का उपयोग नहीं करते हैं क्योंकि हम स्मार्ट पॉइंटर्स का उपयोग करते हैं। किसी भी तरह, मैं नाइटपार्टिंग कर रहा हूं।
फ्लोरियन

3
@krynr: मैं विनम्रता से असहमत हूँ। आप जो देखते हैं और टाइप करते हैं , वह मायने रखता है । यह आपके लिए मायने नहीं रखता है कि यह सब पर्दे के पीछे कैसे काम करता है: यह वह बात है जो अमूर्त है।
मैथ्यू एम।

5

C में, क्लासिक उपयोग qsort फ़ंक्शन है , जहां चौथे पैरामीटर को क्रम के भीतर ऑर्डर करने के लिए उपयोग करने के लिए एक फ़ंक्शन के लिए पॉइंटर है। C ++ में, एक व्यक्ति इस तरह की चीज़ के लिए फंक्शनलर्स (ऑब्जेक्ट्स जो फ़ंक्शन की तरह दिखता है) का उपयोग करेगा।


2
@ केनीटीएम: मैं सी मानक पुस्तकालय में इसका एकमात्र उदाहरण बता रहा था। आपके द्वारा दिए गए उदाहरण तीसरे पक्ष के पुस्तकालयों का हिस्सा हैं।
बिली ओनेल

5

मैंने एब्सट्रैक्शन लेयर बनाने के लिए हाल ही में फंक्शन पॉइंटर्स का इस्तेमाल किया।

मेरे पास शुद्ध C में लिखा गया एक प्रोग्राम है जो एम्बेडेड सिस्टम पर चलता है। यह कई हार्डवेयर वेरिएंट को सपोर्ट करता है। मेरे द्वारा चलाए जा रहे हार्डवेयर के आधार पर, इसे कुछ फ़ंक्शन के विभिन्न संस्करणों को कॉल करने की आवश्यकता है।

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

मैं उचित फ़ंक्शन संस्करणों का चयन करने के लिए स्विच / केस स्टेटमेंट का उपयोग करता था, लेकिन यह अव्यवहारिक हो गया क्योंकि कार्यक्रम अधिक से अधिक हार्डवेयर अनुदान का समर्थन करने के लिए बढ़ गया। मुझे सभी जगह केस स्टेटमेंट जोड़ने पड़े।

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


3

जैसा कि रिच ने ऊपर कहा था, विंडोज में फ़ंक्शन पॉइंटर्स के लिए कुछ सामान्य है जो फ़ंक्शन को स्टोर करने के लिए संदर्भित करता है।

जब आप C languageविंडोज प्लेटफॉर्म पर प्रोग्रामिंग करते हैं, तो आप मूल रूप से प्राथमिक मेमोरी (उपयोग LoadLibrary) में कुछ DLL फ़ाइल लोड करते हैं और DLL में संग्रहीत फ़ंक्शन का उपयोग करने के लिए आपको फ़ंक्शन पॉइंटर्स बनाने और इन पते (उपयोग GetProcAddress) को इंगित करने की आवश्यकता होती है ।

संदर्भ:


2

फंक्शन पॉइंटर्स का उपयोग C में किया जा सकता है ताकि एक इंटरफ़ेस बनाया जा सके जिसके लिए प्रोग्राम किया जा सके। रनटाइम में आवश्यक विशिष्ट कार्यक्षमता के आधार पर, एक अलग कार्यान्वयन फ़ंक्शन पॉइंटर को सौंपा जा सकता है।


2

उनमें से मेरा मुख्य उपयोग कॉलबैक रहा है: जब आपको बाद में कॉल करने के लिए फ़ंक्शन के बारे में जानकारी सहेजने की आवश्यकता होती है ।

कहो तुम बॉम्बरमैन लिख रहे हो। व्यक्ति द्वारा बम गिराने के 5 सेकंड बाद, इसे विस्फोट करना चाहिए ( explode()फ़ंक्शन को कॉल करें )।

अब इसे करने के 2 तरीके हैं। एक तरीका यह है कि स्क्रीन पर सभी बमों की "जांच" करके देखें कि वे मुख्य लूप में विस्फोट करने के लिए तैयार हैं या नहीं।

foreach bomb in game 
   if bomb.boomtime()
       bomb.explode()

दूसरा तरीका यह है कि अपने क्लॉक सिस्टम पर कॉलबैक अटैच करें। जब एक बम लगाया जाता है, तो आप इसे कॉल बम बनाने के लिए कहते हैंसमय सही होने पर (बम) कॉल करें

// user placed a bomb
Bomb* bomb = new Bomb()
make callback( function=bomb.explode, time=5 seconds ) ;

// IN the main loop:
foreach callback in callbacks
    if callback.timeToRun
         callback.function()

यहां कोई भी फ़ंक्शनcallback.function() हो सकता है , क्योंकि यह एक फ़ंक्शन पॉइंटर है।


प्रश्न को [C] और [C ++] के साथ टैग किया गया है, किसी अन्य भाषा के टैग के साथ नहीं। इस प्रकार, किसी अन्य भाषा में कोड स्निपेट प्रदान करना थोड़ा सा विषय है।
सेंटेस्टर - मोनिका

2

फ़ंक्शन पॉइंटर का उपयोग

उपयोगकर्ता इनपुट के आधार पर फ़ंक्शन को गतिशील रूप से कॉल करने के लिए । इस मामले में स्ट्रिंग और फ़ंक्शन पॉइंटर का मानचित्र बनाकर।

#include<iostream>
#include<map>
using namespace std;
//typedef  map<string, int (*)(int x, int y) > funMap;
#define funMap map<string, int (*)(int, int)>
funMap objFunMap;

int Add(int x, int y)
{
    return x+y;
}
int Sub(int x, int y)
{
        return x-y;
}
int Multi(int x, int y)
{
        return x*y;
}
void initializeFunc()
{
        objFunMap["Add"]=Add;
        objFunMap["Sub"]=Sub;
        objFunMap["Multi"]=Multi;
}
int main()
{
    initializeFunc();

    while(1)
    {
        string func;
        cout<<"Enter your choice( 1. Add 2. Sub 3. Multi) : ";
        int no, a, b;
        cin>>no;

        if(no==1)
            func = "Add";
        else if(no==2)
            func = "Sub";
        else if(no==3)
            func = "Multi";
        else 
            break;

        cout<<"\nEnter 2 no :";
                cin>>a>>b;

        //function is called using function pointer based on user input
        //If user input is 2, and a=10, b=3 then below line will expand as "objFuncMap["Sub"](10, 3)"
        int ret = objFunMap[func](a, b);      
        cout<<ret<<endl;
    }
    return 0;
}

इस तरह हमने अपने वास्तविक कंपनी कोड में फ़ंक्शन पॉइंटर का उपयोग किया है। आप 'n' फ़ंक्शन की संख्या लिख ​​सकते हैं और इस पद्धति का उपयोग करके उन्हें कॉल कर सकते हैं।

उत्पादन:

    अपनी पसंद दर्ज करें (1. जोड़ें 2. उप 3. बहु): 1
    2 नंबर: 2 4 दर्ज करें
    6
    अपनी पसंद दर्ज करें (1. जोड़ें 2. उप 3. बहु): 2
    2 नंबर: 10 3 दर्ज करें
    7
    अपनी पसंद दर्ज करें (1. जोड़ें 2. उप 3. बहु): 3
    2 नंबर: 3 6 दर्ज करें
    18

2

अन्य अच्छे उत्तरों के अलावा एक अलग परिप्रेक्ष्य:

सी में, आप केवल फ़ंक्शन पॉइंटर्स का उपयोग करते हैं, न कि (सीधे) फ़ंक्शन।

मेरा मतलब है, आप फ़ंक्शन लिखते हैं, लेकिन आप कार्यों में हेरफेर नहीं कर सकते । किसी फ़ंक्शन का कोई रन-टाइम प्रतिनिधित्व नहीं है जैसे कि आप उपयोग करने में सक्षम हैं। आप "एक फ़ंक्शन" भी नहीं कह सकते। जब आप लिखते हैं:

my_function(my_arg);

आप वास्तव में क्या कह रहे हैं " my_functionनिर्दिष्ट तर्क के साथ पॉइंटर पर कॉल करें "। आप एक फ़ंक्शन पॉइंटर के माध्यम से कॉल कर रहे हैं। इस समारोह सूचक को क्षय का मतलब है कि निम्न कमांड पिछले समारोह कॉल के बराबर हैं:

(&my_function)(my_arg);
(*my_function)(my_arg);
(**my_function)(my_arg);
(&**my_function)(my_arg);
(***my_function)(my_arg);

और इतने पर (धन्यवाद @LuuVinhPhuc)।

इसलिए, आप पहले से ही फ़ंक्शन पॉइंटर्स को मान के रूप में उपयोग कर रहे हैं । स्पष्ट रूप से आप उन मूल्यों के लिए चर रखना चाहेंगे - और यहाँ वह जगह है जहाँ अन्य उपयोगों में अन्य मेटियन आते हैं: बहुरूपता / अनुकूलन (जैसे qsort में), कॉलबैक, जंप टेबल आदि।

C ++ में चीजें थोड़ी अधिक जटिल हैं, क्योंकि हमारे पास लैम्ब्डा है, और ऑब्जेक्ट्स operator()और यहां तक ​​कि एक std::functionक्लास भी है , लेकिन सिद्धांत अभी भी ज्यादातर समान है।


2
और भी अधिक दिलचस्प है, तो आप समारोह कॉल कर सकते हैं के रूप में (&my_function)(my_arg), (*my_function)(my_arg), (**my_function)(my_arg), (&**my_function)(my_arg), (***my_function)(my_arg)... क्योंकि कार्यों समारोह संकेत करने के लिए क्षय
phuclv

1

OO भाषाओं के लिए, पर्दे के पीछे बहुरूपी कॉल करने के लिए (यह C कुछ बिंदु तक मुझे लगता है कि मान्य है)।

इसके अलावा, वे रनटाइम के दौरान किसी अन्य फ़ंक्शन (फू) के लिए अलग व्यवहार को इंजेक्ट करने के लिए बहुत उपयोगी होते हैं। यह फ़ंक्शन फू उच्च-क्रम फ़ंक्शन बनाता है। इसके अलावा यह लचीलापन है, जो फू कोड को अधिक पठनीय बनाता है क्योंकि इससे आप "if-else" के उस अतिरिक्त तर्क को खींच सकते हैं।

यह पायथन में कई अन्य उपयोगी चीजों को सक्षम करता है जैसे जनरेटर, क्लोजर आदि।


0

मैं 1-बाइट ऑपकोड वाले माइक्रोप्रोसेसरों के अनुकरण के लिए बड़े पैमाने पर फ़ंक्शन पॉइंटर्स का उपयोग करता हूं। 256 फ़ंक्शन पॉइंटर्स की एक सरणी इसे लागू करने का प्राकृतिक तरीका है।


0

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


0

मैं यहाँ कुछ हद तक व्यापक सूची देने की कोशिश करूँगा:

  • कॉलबैक : उपयोगकर्ता आपूर्ति कोड के साथ कुछ (पुस्तकालय) कार्यक्षमता को अनुकूलित करें। प्रमुख उदाहरण है qsort(), लेकिन घटनाओं को संभालने के लिए भी उपयोगी है (जैसे कि बटन पर कॉलबैक होने पर उसे क्लिक किया जाता है), या एक धागा शुरू करने के लिए आवश्यक है! pthread_create())।

  • बहुरूपता : C ++ वर्ग में व्यवहार्यता कुछ और नहीं, बल्कि फ़ंक्शन संकेत तालिका है। और C प्रोग्राम अपनी कुछ वस्तुओं के लिए एक विकल्प प्रदान करने का विकल्प भी चुन सकता है:

    struct Base;
    struct Base_vtable {
        void (*destruct)(struct Base* me);
    };
    struct Base {
        struct Base_vtable* vtable;
    };
    
    struct Derived;
    struct Derived_vtable {
        struct Base_vtable;
        void (*frobnicate)(struct Derived* me);
    };
    struct Derived {
        struct Base;
        int bar, baz;
    }

    के निर्माता Derivedतो अपने तय करेगा vtableकी व्युत्पन्न की क्लास के कार्यान्वयन के साथ एक वैश्विक वस्तु के लिए सदस्य चर destructऔर frobnicate, और कोड है कि संहार करने के लिए एक की जरूरत है struct Base*बस कहेंगे base->vtable->destruct(base), जो नाशक का सही संस्करण कहेंगे, जिनमें से स्वतंत्र वर्ग व्युत्पन्न baseकरने के लिए वास्तव में अंक ।

    फंक्शन पॉइंटर्स के बिना, पॉलीमॉर्फिज्म को स्विच कंस्ट्रक्शन की एक सेना के साथ कोडित करना होगा

    switch(me->type) {
        case TYPE_BASE: base_implementation(); break;
        case TYPE_DERIVED1: derived1_implementation(); break;
        case TYPE_DERIVED2: derived2_implementation(); break;
        case TYPE_DERIVED3: derived3_implementation(); break;
    }

    यह बल्कि बल्कि जल्दी से बेकार हो जाता है।

  • डायनामिकली लोडेड कोड : जब कोई प्रोग्राम किसी मॉड्यूल को मेमोरी में लोड करता है और उसके कोड में कॉल करने की कोशिश करता है, तो उसे फंक्शन पॉइंटर से गुजरना चाहिए।

फ़ंक्शन पॉइंटर्स के सभी उपयोग जिन्हें मैंने देखा है, इन तीन व्यापक वर्गों में से एक में आते हैं।

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