2013-02-01 28 views
5

फ़ंक्शन ऑब्जेक्ट करने के लिए पॉइंटर असाइन करें क्या यह C++ में संभव है?किसी फ़ंक्शन में पॉइंटर को ऑब्जेक्ट

void (*f)(); 

और और एक समारोह वस्तु:

class A 
{ 
public: 
    void operator()() { cout << "functor\n"; } 
}; 

यह f पता करने के लिए आवंटित करने के लिए संभव है उदाहरण के लिए मैं एक समारोह है कि कोई पैरामीटर और उसके वापसी प्रकार शून्य है लेता है करने के लिए एक सूचक है A ऑब्जेक्ट का? और जब मैं A फ़ंक्शन को कॉल करने के लिए f() पर कॉल करता हूं?

मैं इस कोशिश की, लेकिन यह काम नहीं करता:

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    void operator()() { cout << "functorA\n"; } 
}; 

int main() 
{ 
    A ob; 
    ob(); 
    void (*f)(); 
    f = &ob; 
    f();  // Call ob(); 
    return 0; 
} 

मैं C:\Users\iuliuh\QtTests\functor_test\main.cpp:15: error: C2440: '=' : cannot convert from 'A *' to 'void (__cdecl *)(void)' There is no context in which this conversion is possible

वहाँ किसी भी तरह से इस लक्ष्य को हासिल करने के लिए है मिल सकता है?

+3

तुम सिर्फ 'std :: समारोह ' का उपयोग नहीं कर सकते हैं? – chris

+0

क्या पुराने मानक के साथ ऐसा करने का कोई तरीका है, सी ++ 11 से पहले एक? –

उत्तर

5

आप जिस तरह से आपके द्वारा निर्दिष्ट में यह नहीं कर सकते के साथ खेल सकते है क्योंकि:

  1. ऑपरेटर() एक nonstatic समारोह (मानकों की आवश्यकता)
  2. एक nonstatic कार्य करने के लिए एक सूचक एक अंतर्निहित पैरामीटर होना आवश्यक होना चाहिए - वर्ग उदाहरण के लिए सूचक
  3. च करने के लिए अपने कॉल() कोई संकेत वस्तु एक के जो उदाहरण पर अपने समारोह

कहा जाता है सी ++ 11 और std :: समारोह का उपयोग नहीं देता है, के रूप में स्टीफ़न रोलां ने कहा, काम कर सकता है - आप बंधन में ऑब्जेक्ट के लिए सूचक को निर्दिष्ट कर दिया जाएगा:

std::function<void(void)> f = std::bind(&A::operator(), &ob); 

(question देखें std :: सदस्य कार्यों पर समारोह का उपयोग करने पर)

+1

+1: std :: bind –

2

हाँ, यह एक तरह से संभव एक सी ++ 1/C++ 0x सुविधा का उपयोग कर रहा है, लेकिन प्राप्त करने के लिए इस आप std :: समारोह जो दो प्रकार, कार्यों और वस्तु कार्यों के लिए पता कर सकते हैं का उपयोग करना चाहिए।

#include <functional> 

class A 
{ 
public: 
    void operator()() { } 
}; 

int main() 
{ 
    std::function<void(void)> aFunction; 
    A ob; 

    aFunction = ob; 

// or as another user said 
// aFunction = std::bind(&A:operator(), &ob); 

    aFunction(); 

    void (*f)(); 

    aFunction = f; 

    aFunction(); 

    return 0; 
} 

और यदि आप सी ++ 03 के साथ फंस रहे हैं, आप, std::mem_fun और std::ptr_fun

3

आप सी ++ 11, std::function इस्तेमाल कर सकते हैं का उपयोग करते हैं

#include <functional> 

std::function<void()> f; 

int main() 
{ 
    A ob; 
    ob(); 

    f = ob; // f refers to ob 
    f();  // Call ob(); 
    return 0; 
} 
1

कैसे इस तरह की कुछ वैकल्पिक हल के बारे में:

मूल रूप से आप सदस्य कार्य करता है और कार्यों बुला का एक आम तरीका करना चाहते हैं। फिर शायद आप एक रैपर बना सकते हैं जो किसी फ़ंक्शन या सदस्य फ़ंक्शन के लिए जेनेरिक पॉइंटर का प्रतिनिधित्व करेगा। मान लें कि आपके पास Base कक्षा है और आप सभी व्युत्पन्न कक्षाओं के operator() को आमंत्रित करने में सक्षम होना चाहते हैं।

class Base 
{ 
public: 
    virtual void operator()() = 0; 
}; 

class A : public Base 
{ 
public: 
    void operator()(){ std::cout << "A()" << std::endl; } 
}; 

void function() 
{ 
    std::cout << "function" << std::endl; 
} 

आप एक आवरण है कि आप अपने कस्टम सूचक (MyFncPtr) के निर्माण के लिए अनुमति देता है बनाते हैं::

typedef void (Base::*BaseFncPtr)(); 
typedef void (*FncPtr)(); 

class MyFncPtr 
{ 
public: 
    MyFncPtr(FncPtr f) : fnc(f), baseObj(NULL), baseFnc(NULL) { } 
    MyFncPtr(BaseFncPtr fPtr, Base* objPtr) : baseFnc(fPtr), baseObj(objPtr), fnc(NULL) { } 
    void invoke() 
    { 
     if (baseObj && baseFnc) 
      (baseObj->*baseFnc)(); 
     else if (fnc) 
      fnc(); 
    } 

private: 
    BaseFncPtr baseFnc; 
    Base* baseObj; 
    FncPtr fnc; 
}; 

आप इसे पसंद प्राप्त कर सकते थे तो फिर तुम भी एक function() है कि आप के रूप में अच्छी तरह से आह्वान करना चाहते हैं इस:

A a; 
MyFncPtr myPtr(&Base::operator(), &a); 
myPtr.invoke(); 
MyFncPtr myPtr2(function); 
myPtr2.invoke(); 

आउटपुट:

A() 
function 

आशा इस मदद करता है :)

+0

के लिए बस ध्यान दें कि यह अंतिम समाधान है कि यह अंतिम समाधान है। जब आप मूल 'बेसओबीजे' नष्ट हो जाते हैं, तो आपको लटकने वाले पॉइंटर्स के साथ समस्या पर विचार करना चाहिए। स्मार्ट पॉइंटर्स का उपयोग किया जा सकता है ताकि स्मार्ट पॉइंटर्स का उपयोग किया जा सके ताकि यह अधिक उचित समाधान हो सके :) – LihO

+0

+1 बिना काम के काम करता है नई सी ++ 11 विशेषताएं। धन्यवाद! –

+0

@ जॉनस्मिथ: आपका स्वागत है :) हाँ, मैं यह इंगित करना चाहता था कि सी ++ 0x/सी ++ 11 पर निर्भर लोगों के मुकाबले अन्य समाधान हैं;) – LihO