2010-03-23 10 views
11

मैं जानता हूँ कि इस बात काम करता है:सी ++ और ओपनजीएल में किसी अन्य फ़ंक्शन के लिए तर्क के रूप में क्लास विधि को कैसे पास किया जाए?

void myDisplay() 
{ 
... 
} 
int main() 
{ 
... 
glutDisplayFunc(myDisplay) 
... 
} 

तो मैं myDisplay() एक वर्ग है कि मैं बनाया करने के लिए समारोह में शामिल करने की कोशिश की। क्योंकि मैं भविष्य में इसे एक अलग वर्ग के साथ अधिभारित करना चाहता हूं। हालांकि, संकलक शिकायत है कि

argument of type 'void (ClassBlah::)()' does not match 'void(*)()' .

यहाँ है कि मैं क्या करने की कोशिश है:

class ClassBlah 
{ 
    .... 
    void myDisplay() 
    .... 
} 
...... 
int main() 
{ 

    ... 
    ClassBlah blah 
    glutDisplayFunc(blah.myDisplay) 
    ... 
} 

किसी को भी जानता है कि कैसे इस समस्या को ठीक करने के लिए करता है? बहुत धन्यवाद।

उत्तर

9

सबसे पहले, गैर-स्थिर सदस्य कार्यों में एक निहित "यह" सूचक है, इसलिए आपको को ClassBlah में स्थिर होने की आवश्यकता होगी। इस सीमा के आसपास काम करना अजीब है, यही कारण है कि सी ++ एफएसी लाइट don't do it

फिर, आप ClassBlah::myDisplay के रूप में कार्यों को पारित करने में सक्षम होना चाहिए।

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

1

आप उदाहरण के एक सदस्य समारोह पर एक धागा बनाने के लिए, सदस्य कार्यों के लिए बूस्ट बाँध का उपयोग कर सकते हैं:

class classA 
{ 
public: 
    void memberThreadFunc(int i); 
}; 

void main() 
{ 
    classA a; 
    boost::thread(boost::bind(&classA::memberFunc, &a, 123)); 
} 
+0

यह अच्छा है। अगर सदस्य थ्रेडफनक आभासी है, और उप-वर्ग के लिए एक बिंदु है तो यह ठीक से काम करता है? – kibibu

+1

मुझे संदेह है कि बूस्ट :: बाइंड यहां काम करेगा, क्योंकि निश्चित रूप से एक संरचना लौटाती है जिसमें एक() ऑपरेटर होता है, जो glutDisplayFunc का उपयोग नहीं कर सकता है। – Thanatos

+4

बाइंड यहां मदद नहीं कर सकता है। बुलाए जाने वाले फ़ंक्शन को 'शून्य (*)() 'प्रकार की कॉलबैक की आवश्यकता होती है। 0-एरी फ़ंक्शन ऑब्जेक्ट का उपयोग नहीं किया जा सकता है। –

0

आप नहीं कर सकते। glutDisplayFuncvoid(*)() का पैरामीटर लेता है, void (ClassBlah::)() नहीं। जब तक आप ग्लूट के स्रोत को बदलने में सक्षम और सक्षम नहीं होते हैं, तो आप भाग्य से बाहर हैं।


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

5

मैं इस समस्या में एक सी ++ ग्लूट इंजन लिखने में भाग गया। यहाँ कैसे मैं इसे चारों ओर से काम किया है:

मैं अपने program.cpp/main.cpp के शीर्ष पर इन रखा

// Function prototypes 
void doRendering(void); 
void processMouse(int, int) ; 
void processMouseClick(int button, int state, int x, int y); 
void keyboardInput(unsigned char c, int x, int y); 

यहां भरमार के कॉलबैक करने के लिए इन कार्यों असाइन करें:

glutDisplayFunc(doRendering); 
glutIdleFunc(doRendering); 
glutPassiveMotionFunc(processMouse); 
glutMotionFunc(processMouse); 
glutMouseFunc(processMouseClick); 
glutKeyboardFunc(keyboardInput); 

बनाएं मेरी अपनी कक्षा जो इन्हें स्वयं ही संभालती है और फिर हमारे स्थिर कार्यों की सामग्री को केवल इस वर्ग के उदाहरण पर विधियों को कॉल करती है। आपके मुख्य कार्य को मुख्य रूप से कक्षा का एक नया उदाहरण बनाना चाहिए (मेरे मामले में ... ऐप * newApp)।

void doRendering(void) 
{ 
    newApp->updateScene(); 
    newApp->drawScene(); 
} 

void processMouse(int x, int y) 
{ 
    newApp->processMouse(x, y); 
} 

void processMouseClick(int button, int state, int x, int y) 
{ 
    newApp->processMouseClick(button, state, x, y); 
} 

void keyboardInput(unsigned char c, int x, int y) 
{ 
    newApp->keyboardInput(c, x, y); 
} 

आशा है कि यह समझाएगा।

3

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

/** 
     Class argon is defined in external header file. 
*/ 

Argon *argonPtr; 

void renderScene(); 

int main() 
{  
    Argon argon; 
    argonPtr = &argon; 

    glutDisplayFunc(render); 
} 

void render() 
{ 
    RenderStuff(); 
    argonPtr->Render(); 
} 

आशा है कि यह आपके लिए काम करता है, मेरे लिए यह करता है।

+0

यह मेरे लिए काम किया, धन्यवाद! लेकिन मुझे यह जानकर उत्सुकता है कि यह इस तरह से कितना अच्छा है? – Kahin

+1

जैसा कि कुछ लोगों ने उल्लेख किया है, glutDisplayFunc को स्मृति में पॉइंटर प्राप्त करना होगा जहां आप प्रतिपादन के कार्यान्वयन को संग्रहीत करते हैं। परिभाषा के अनुसार यह तर्क प्राप्त नहीं कर सकता है, इसलिए ऐसा करने का एकमात्र तरीका वैश्विक चर पर काम करना है। मैं मानता हूं कि यह क्रूर और बदसूरत है और ओओपी का सम्मान नहीं करता है। लेकिन दूसरी तरफ, सी ओओपी भाषा नहीं है। कई रैपर हैं, और एपीआई का नया संस्करण जिसका उपयोग ओओपी को संरक्षित करने के लिए किया जा सकता है। आप @ कोर्विन जैसे कुछ भी कर सकते हैं, उन्होंने इसे बहुत साफ तरीके से हल किया है, लेकिन मूल विचार बाहरी से बाहर परिवर्तनीय पर काम करना है। मेरी राय में यह एक ही विचार कम/कम है। – bartekordek