2008-12-05 13 views
26

मैं कुछ इस तरह कर रहा हूँ:क्या सी ++ कक्षा के अंदर सिग्नल का उपयोग करना संभव है?

#include <signal.h> 

class myClass { 

    public: 

    void myFunction() 
    { 
    signal(SIGIO,myHandler); 
    } 

    void myHandler (int signum) 
    { 
    /** 
    * Handling code 
    */ 
    } 

    } 

मैं Ubuntu पर काम कर रहा हूँ, जीसीसी का उपयोग कर।

लेकिन यह संकलित नहीं होगा। यह शिकायत कर रहा है:

error: the argument with type void (MyClass::)(int) doesn't agree with void (*) (int)

कोई संकेत? या शायद यह है कि मैं कक्षाओं के अंदर एक संकेत का उपयोग नहीं कर सकता? सिग्नल केवल सी में अनुमति है?

त्रुटि संदेश एक अनुमानित अनुवाद है क्योंकि मेरा कंपाइलर अंग्रेजी में नहीं है।

+0

, खबरदार कि सिग्नल threadsafe नहीं कर रहे हैं, ताकि आप इस अगर necesarry –

+0

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

+0

@ रॉबर्ट गोल्ड: सच; लेकिन इस विषय के लिए वास्तव में प्रासंगिक नहीं है। –

उत्तर

35

सिग्नल का दूसरा पैरामीटर एक इंट को स्वीकार करने और शून्य लौटने वाले फ़ंक्शन के लिए सूचक होना चाहिए। जो आप सिग्नल में जा रहे हैं वह सदस्य फ़ंक्शन को एक इंट और रिटर्निंग शून्य (इसके प्रकार void (myClass::*)(int)) को स्वीकार करने वाला एक सूचक है। मैं तीन संभावनाएं देख सकते हैं इस मुद्दे पर काबू पाने के लिए:

1 - अपने विधि myHandler स्थिर हो सकता है: इस महान है, यह स्थिर

class myClass 
{ 
    public: 
    void myFunction() 
    { 
     signal(SIGIO, myClass::myHandler); 
    } 

    static void myHandler (int signum) 
    { 
     // handling code 
    } 
}; 

2 - अपने विधि स्थिर नहीं होना चाहिए: यदि आप ' केवल एक उदाहरण के साथ सिग्नल का उपयोग करने की योजना बना रहे हैं, आप एक निजी स्थैतिक वस्तु बना सकते हैं, और एक स्थिर विधि लिख सकते हैं जो इस ऑब्जेक्ट पर विधि को कॉल करे।

class myClass 
{ 
    public: 
    void myFunction() 
    { 
     signal(SIGIO, myClass::static_myHandler); 
    } 

    void myHandler (int signum) 
    { 
     // handling code 
    } 

    static void static_myHandler(int signum) 
    { 
     instance.myHandler(signum); 
    } 

    private: 
    static myClass instance; 
}; 

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

class myClass 
{ 
    public: 
    void myFunction() // registers a handler 
    { 
     instances.push_back(this); 
    } 

    void myHandler (int signum) 
    { 
     // handling code 
    } 

    static void callHandlers (int signum) // calls the handlers 
    { 
     std::for_each(instances.begin(), 
         instances.end(), 
         std::bind2nd(std::mem_fun(&myClass::myHandler), signum)); 
    } 
    private: 
    static std::vector<myClass *> instances; 
}; 

और कहीं,

signal(SIGIO, myClass::callHandlers); 

लेकिन करने के लिए एक कॉल करना मुझे लगता है कि यदि आप अंतिम समाधान का उपयोग करते हैं, तो आपको शायद अपने हैंडलिंग डिज़ाइन को बदलने के बारे में सोचना चाहिए :-)!

+0

आपका दूसरा उदाहरण मानक सी ++ नहीं है। – dalle

+0

ऐसा इसलिए है क्योंकि मैं स्थिर कीवर्ड भूल गया था? यदि हां, तो यह सही है! –

+0

यह त्रुटि है जब मैं आपकी दूसरी विधि का पालन करता हूं 'त्रुटि:' उदाहरण 'इस दायरे में घोषित नहीं किया गया था' – molecule

1

इस निम्नलिखित खंड (33.2 किमी) पढ़ें:

C++ FAQ - pointers-to-members

+0

टूटा लिंक, इसलिए बेकार जवाब। –

+0

6 साल पहले पोस्ट किया गया लिंक! – Baget

9

एक पद्धति के लिए एक सूचक पास करने के लिए तो वह एक स्थिर विधि होना चाहिए और आप वर्ग के नाम का उल्लेख करना होगा।

इस प्रयास करें:

class myClass { 
    void myFunction() 
    { 
    signal(SIGIO, myClass::myHandler); 
    } 

    static void myHandler (int signum) 
    { 
    // blabla 
    } 
}; 

और तुम भी लिंक Baget द्वारा आपूर्ति की, paragraph 33.2 in the C++ FAQ पढ़ना चाहिए।

+0

सरल और सटीक! – parasrish

1

दरअसल, सी ++ सिग्नल हैंडलर को सी और सी ++ दोनों में मौजूद किसी भी सुविधा का उपयोग करने की अनुमति नहीं है (सिवाय इसके कि सी ++ 11 में वे परमाणुओं का उपयोग कर सकते हैं), और सी लिंकेज का उपयोग करने की आवश्यकता है। का हवाला देते हुए C++11 draft n3242 खंड 18.10   "अन्य रनटाइम समर्थन" [support.runtime] (पैरा 8),

The common subset of the C and C++ languages consists of all declarations, definitions, and expressions that may appear in a well formed C++ program and also in a conforming C program. A POF (“plain old function”) is a function that uses only features from this common subset, and that does not directly or indirectly use any function that is not a POF, except that it may use functions defined in Clause 29 that are not member functions. All signal handlers shall have C linkage. A POF that could be used as a signal handler in a conforming C program does not produce undefined behavior when used as a signal handler in a C++ program. The behavior of any other function used as a signal handler in a C++ program is implementation-defined.

(खण्ड 29 एटोमिक्स पर एक होने के।)

1
#include <signal.h> 

class myClass { 

private: 
    static myClass* me; 

public: 
    myClass(){ me=this; } 

    void myFunction(){ 
    signal(SIGIO,myClass::myHandler); 
    } 

    void my_method(){ } 

    static void myHandler (int signum){ 
    me->my_method(); 
} 
} 
+0

हालांकि यह कोड प्रश्न का उत्तर दे सकता है, इस सवाल का जवाब देने के तरीके के बारे में अतिरिक्त संदर्भ प्रदान करना और/या कैसे यह दीर्घकालिक मूल्य में सुधार करता है। – NathanOliver

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

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