2015-02-06 6 views
5

मैं वर्तमान में FLTK जीयूआई पुस्तकालय के साथ प्रयोग कर रहा हूँ, लेकिन वास्तव में यकीन है कि क्या कॉलबैक कार्यों — साथ चल रहा है नहीं कर रहा हूँ विशेष रूप से प्रकार कास्टिंग सामान थोड़ा मेरे लिए विदेशी है। नीचे दिया गया उदाहरण "प्रेस" लेबल वाले बटन के साथ एक मूल विंडो दिखाता है। जब आप बटन दबाते हैं तो लेबल "हो गया" में बदल जाता है।प्रकार कास्टिंग/कॉलबैक कार्य

लेबल कि कॉलबैक फ़ंक्शन पर पारित हो जाता है प्रकार const char* के रूप में घोषित किया जाता है और फिर इसे टाइप करने के लिए void* डाली है, लेकिन यह एक std::string के रूप में इस घोषणा करने के लिए संभव है और फिर void* लिए डाली? मैं char नोटेशन से आधुनिक सी ++ तारों का उपयोग करना पसंद करता हूं।

इसके अलावा, है एक प्रकार से दूसरे में कास्टिंग का सबसे अच्छा तरीका नीचे वाक्य रचना? मैं static_cast<type>() देखा है पहले इस्तेमाल किया लेकिन क्या सबसे सुरक्षित/सबसे अच्छा void* या ठीक इसके विपरीत है और क्यों करने के लिए const char* से एक डाली करने के लिए तरीका है? सी ++ 11 क्या सिफारिश करेगा?

#include <FL/Fl.H> 
#include <FL/Fl_Window.H> 
#include <FL/Fl_Button.H> 
#include <FL/Fl_Native_File_Chooser.H> 
#include <string> 

void xyz_callback(Fl_Widget* w, void* userdata) 
{ 

    Fl_Button* b = (Fl_Button*)w; //cast widget w to button and assign to b 

    b->label((const char*)userdata); //cast userdata back to type const char* 
} 


int main(int argc, char **argv) 
{ 
    Fl_Window *window = new Fl_Window(340,180); 
    Fl_Button *button = new Fl_Button(20,40,300,100, "label"); 
    button->label("Press"); 
    button->labelfont(FL_BOLD+FL_ITALIC); 
    button->labelsize(36); 
    button->labeltype(FL_SHADOW_LABEL); 
    button->when(FL_WHEN_RELEASE); 

    const char* word = "Done"; 
    button->callback(xyz_callback, (void*)word); //cast word to type void* 

    window->end(); 
    window->show(argc, argv); 
    return Fl::run(); 
} 
+0

लेकिन यह एक std :: स्ट्रिंग के रूप में घोषित करने के लिए संभव है और फिर कास्ट करने के लिए "शून्य *"? हाँ। –

+1

@ BartekBanachewicz क्या आप std :: string या std :: string पर पॉइंटर डालना चाहते हैं? – harper

+0

ठीक है, इसके लिए एक सूचक। –

उत्तर

6

(T)a शैली कास्टिंग, भी सी-शैली कास्टिंग के रूप में जाना, यह वास्तव में सबसे खराब रास्ता सी ++ में एक स्पष्ट रूपांतरण करने के लिए। ऐसा इसलिए है क्योंकि यह सबसे शक्तिशाली — है, यह आसानी से गंभीर त्रुटियों को छिपाने, लगभग कुछ भी रूपांतरित कर देगा। यह सी में उपलब्ध स्पष्ट प्रकार के रूपांतरण का एकमात्र रूप है, और इसे सी ++ द्वारा विरासत में मिलाया गया था, लेकिन कभी भी गुणवत्ता C++ कोड में इसका उपयोग नहीं किया जाना चाहिए।

void* को word के कलाकारों अनावश्यक — किसी भी सूचक प्रकार आपत्ति उठाने का परोक्ष void के लिए सूचक में बदला जा सकता है।

कॉलबैक में const char* पर कास्ट आवश्यक है, लेकिन static_cast<const char*>(userdata) के साथ किया जा सकता है। कि जीवन पर निर्भर करता है:

प्रश्न के बारे में std::string का समाधान करना। आप std::string* को void* पर परिवर्तित कर सकते हैं और इसे कॉलबैक पर भेज सकते हैं। वहाँ में, आप इसे str::string* वापस करने के लिए डाली चाहते हैं (और फिर c_str() पुनः प्राप्त यह label कार्य करने के लिए पारित करने के लिए से)। लेकिन आपको यह सुनिश्चित करना होगा कि कॉलबैक के समय तक std::string की ओर इशारा किया गया है (अभी भी दायरे से बाहर नहीं गया है)। यदि आप इसे main में स्थानीय चर बनाते हैं, तो आप बहुत अधिक सुरक्षित हैं।

आप इसे उस तरह से करते हैं, कोड इस तरह दिखेगा:

void xyz_callback(Fl_Widget* w, void* userdata) 
{ 
    Fl_Button* b = static_cast<Fl_Button*>(w); 

    b->label(static_cast<std::string*>(userdata)->c_str()); 
} 


int main(int argc, char **argv) 
{ 
    Fl_Window *window = new Fl_Window(340,180); 
    Fl_Button *button = new Fl_Button(20,40,300,100, "label"); 
    button->label("Press"); 
    button->labelfont(FL_BOLD+FL_ITALIC); 
    button->labelsize(36); 
    button->labeltype(FL_SHADOW_LABEL); 
    button->when(FL_WHEN_RELEASE); 

    std::string word = "Done"; 
    button->callback(xyz_callback, &word); 

    window->end(); 
    window->show(argc, argv); 
    return Fl::run(); 
} 
+0

बहुत धन्यवाद एंग्यू - यह बिल्कुल सही प्रकार की जानकारी है जो मुझे अपने सिर में कुछ चीजों को स्पष्ट करने में मदद करने के लिए आवश्यक है और आपके द्वारा सुझाए गए कोड का उपयोग करके मैं बहुत खुश हूं। जवाब देने का समय निकालने के लिए धन्यवाद! –

+0

@EdwardJeckyll यदि कोई उत्तर आपकी समस्या हल करता है, तो आपको इसे * स्वीकार करने * द्वारा चिह्नित करने पर विचार करना चाहिए (इसके आगे हरे रंग के चेक-चिह्न पर क्लिक करके, प्रति प्रश्न सबसे अधिक स्वीकृत उत्तर पर)। यह प्रश्न को हल करने के रूप में चिह्नित करता है और उत्तर देने वाले और आपको कुछ प्रतिष्ठा देता है। यह कहने का [स्टैक ओवरफ्लो तरीका है "धन्यवाद, यह काम करता है"] (http://stackoverflow.com/help/someone-answers)। – Angew

+0

समझ गया, धन्यवाद एंग्यू। –

0

अपने कॉलबैक आप की तुलना में एक void* अपेक्षा करता है कि कुछ भी करने के लिए एक सूचक पारित कर सकते हैं। लेकिन कॉलबैक को पता होना चाहिए कि तर्क को कैसे संभालना है। इसे इसे एक प्रयोग योग्य प्रकार पर वापस डालना चाहिए।

आप कॉलबैक बदल सकते हैं इतना है कि यह एक std::string के लिए सूचक की उम्मीद है। आप कॉलबैक में एक const char* करना चाहते हैं आप कॉलबैक करने के लिए सी-शैली स्ट्रिंग पारित करने के लिए है:

button->callback(xyz_callback, str.c_str()); 
+0

शून्य 1 - किसी को 'c_str() 'का उपयोग करने और जीवनभर प्रबंधन समस्याओं का वर्णन नहीं करने के लिए कह रहा है, esp। कॉलबैक में उपरोक्त प्रश्न के कोड में अपना कोड छोड़ना चीजों को बहुत ही तोड़ देगा। – Yakk

+0

@Yakk कॉलबैक को समकालिक रूप से कहा जाता है। कॉलबैक को वैसे भी डेटा का स्वामित्व प्राप्त करना होगा। किसी भी स्थानीय चर के लिए एक सूचक को पास करना एक ही समस्या है। लेकिन यह सवाल का हिस्सा नहीं है। आप यहां प्रोग्रामिंग शैली की एक पुस्तक पढ़ने की उम्मीद नहीं कर सकते हैं। – harper

+0

अच्छा बिंदु - वे 'मुख्य' निकास से पहले ':: रन()' करते हैं। – Yakk

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