2009-06-05 14 views
28

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

class Class{ 
public: 
    Class(const std::string &n, Object *(*c)()); 
protected: 
    std::string name;  // Name for subclass 
    Object *(*create)(); // Pointer to creation function for subclass 
}; 

एक स्थिर कक्षा सदस्य गृहीत साथ वस्तु के किसी भी उपवर्ग के लिए, मुझे लगता है कि उपवर्ग के निर्माता के लिए सूचक के साथ प्रारंभ 'बनाने' के लिए सक्षम होना चाहता हूँ।

+0

हालांकि इस तथ्य के बाद 6 साल है - आप देना चाहिए इस बारे में बहुत सारे विचार हैं कि आप वास्तव में अपने स्वयं के प्रतिबिंब तंत्र को कार्यान्वित करना चाहते हैं या नहीं। सबसे पहले टेम्पलेट्स, टाइप_ट्रेट्स और एसएफआईएनएई सिद्धांत का उपयोग करके संकलन-समय 'प्रतिबिंब' के लिए निपटने पर विचार करें; फिर मौजूदा सी ++ प्रतिबिंब पुस्तकालयों में से एक को आजमाएं; और केवल तभी मैं खुद पर जाने पर विचार करता हूं। – einpoklum

उत्तर

52

आप एक निर्माता के पते नहीं ले जा सकते (सी ++ 98 स्टैंडर्ड 12.1/12 कंस्ट्रक्टर्स - "12.1-12 कंस्ट्रक्टर्स -"। एक निर्माता के पते के रूप में नहीं लिया जाएगा ")

आपका सबसे अच्छा शर्त है एक कारखाने समारोह/विधि है कि Object बनाता है और कारखाने के पते के पारित करने के लिए:।

class Object; 

class Class{ 
public: 
    Class(const std::string &n, Object *(*c)()) : name(n), create(c) {}; 
protected: 
    std::string name;  // Name for subclass 
    Object *(*create)(); // Pointer to creation function for subclass 
}; 

class Object {}; 

Object* ObjectFactory() 
{ 
    return new Object; 
} 



int main(int argc, char**argv) 
{ 
    Class foo("myFoo", ObjectFactory); 

    return 0; 
} 
+5

इसे एक टेम्पलेट बनाना इसे वास्तव में "कक्षा" वापस कर देगा: टेम्पलेट ऑब्जेक्ट * ऑब्जेक्ट फैक्ट्री() {वापसी नया टी; } .... कक्षा फू ("myFoo", और ऑब्जेक्ट फैक्ट्री ); –

2

हम्म, अजीब create एक सदस्य चर यानी वर्ग मामलों में ही उपलब्ध है, लेकिन यह करने के इरादे बनाने जा रहा है पहली जगह में एक उदाहरण।

आप एक कन्स्ट्रक्टर का पता नहीं ले सकते हैं, लेकिन आप अपने स्वयं के स्थिर कारखाने के तरीके बना सकते हैं और इसका पता ले सकते हैं।

+1

लाल्टो, जब मैं क्लास ऑब्जेक्ट का निर्माण करता हूं तो मैं एक नाम और एक सृजन समारोह में जाता हूं। मेरा लक्ष्य उन वर्गों की एक सूची है जिनके लिए मैं अपनी परियोजना में कहीं भी संदर्भित कर सकता हूं। एक स्थिर सदस्य समारोह के लिए एक सूचक काम करेगा। – Kareem

+0

और एक और संकेत जोड़ें - प्रदर्शन के लिए बुरा। – Lothar

0

आप तरीकों पर नियमित रूप से समारोह संकेत उपयोग नहीं कर सकते, तो आप विधि संकेत दिए गए, जो विचित्र वाक्य रचना है उपयोग करने के लिए:

void (MyClass::*method_ptr)(int x, int y); 
method_ptr = &MyClass::MyMethod; 

यह आपको MyClass की विधि के लिए एक विधि सूचक देता है - MyMethod। हालांकि यह एक वास्तविक सूचक नहीं है कि यह एक पूर्ण स्मृति पता नहीं है, यह मूल रूप से एक ऑफसेट है (वर्चुअल विरासत के कारण उससे अधिक जटिल है, लेकिन वह सामान एक वर्ग में कार्यान्वयन विशिष्ट है)। तो विधि सूचक का उपयोग करने के लिए, आप एक वर्ग के साथ यह आपूर्ति करने के लिए है इस तरह:

MyClass myclass; 
myclass.*method_ptr(x, y); 

या

MyClass *myclass = new MyClass; 
myclass->*method_ptr(x, y); 
बेशक

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

+6

यह सही नहीं है। और MyClass :: MyMethod आपको MyMethod के वास्तविक निष्पादन योग्य कोड की स्मृति में पता देता है। तरीकों का एक निहित पहला तर्क है, यह सूचक। आप कक्षा के साथ कोई विधि नहीं देते हैं, आप इसे किसी ऑब्जेक्ट (कक्षा का एक उदाहरण, उदाहरण के लिए एक सूचक) के साथ आपूर्ति करते हैं। इस कॉलिंग सम्मेलन को देखो। –

+1

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

+0

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

0

क्यूटी का उपयोग करके, आप क्यूटी प्रतिबिंब तंत्र (QMetaObject) के साथ एक कन्स्ट्रक्टर को कॉल कर सकते हैं यदि आप कन्स्ट्रक्टर को Q_INVOKABLE के रूप में घोषित करते हैं (उससे कुछ और करने के लिए नहीं)।

class MyClass : public QObject { 
    Q_OBJECT 
public: 
    Q_INVOKABLE MyClass(int foo); 
    MyClass *cloningMySelf() { 
    return metaObject()->newInstance(Q_ARG(int, 42)); 
    } 
}; 

मुझे यकीन है कि आप क्यूटी एम्बेड करने के लिए सिर्फ इतना है कि सुविधा ;-) के लिए चाहते हैं नहीं कर रहा हूँ, लेकिन हो सकता है आप जिस तरह से यह करता है पर एक नजर है करना चाहते हैं।

http://doc.qt.io/qt-5/metaobjects.html#meta-object-system

1

लैम्ब्डा शैली:

[](){return new YourClass();} 
+1

कृपया इसके लिए अधिक स्पष्टीकरण/संदर्भ जोड़ने पर विचार करें क्योंकि इससे भविष्य के पाठकों के लिए उत्तर अधिक उपयोगी हो जाता है। – EJoshuaS

+0

निश्चित रूप से, उल्लेख करें कि यह एक सी ++ 11 और बाद की सुविधा है। – Kareem

0

मैं इस एक ही समस्या का सामना करना पड़ा। मेरा समाधान एक टेम्पलेट फ़ंक्शन था जिसे कन्स्ट्रक्टर कहा जाता था।

template<class T> MyClass* create() 
{ 
    return new T; 
} 

एक समारोह सूचक के रूप में उपयोग करने के लिए आसान है:

MyClass* (*createMyClass)(void) = create<MyClass>; 

और MyClass का एक उदाहरण प्राप्त करने के लिए:

MyClass* myClass = createMyClass(); 
संबंधित मुद्दे

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