2012-06-24 19 views
5

मैं एक ऐसा एप्लिकेशन लिखने की कोशिश कर रहा हूं जो रनटाइम के दौरान गतिशील रूप से अपने एक्सटेंशन लोड कर रहा हो। मैंने बूस्ट प्रीप्रोसेसर लाइब्रेरी का इस्तेमाल प्रीप्रोसेसर फ़ंक्शन लिखने के लिए किया था, जिसमें नामों की एक सूची दी गई थी, प्रत्येक नाम के लिए एक वर्ग घोषित करता है (और उनमें से सभी को कुछ सारप्लजिन वर्ग के उप-वर्ग बनाते हैं) और उसके बाद उस कक्षा वाले बूस्ट एमपीएल अनुक्रम की घोषणा करता है। तब मैंने एक कक्षा लिखी जो एबस्ट्रप्लगिन को पॉइंटर की कोशिश करता है अगर इसे एमपीएल अनुक्रम में किसी भी प्रकार से डाला जा सकता है। यहां समस्या यह है कि मेरे प्रीप्रोसेसर फ़ंक्शन को उन सभी एक्सटेंशन की पूरी सूची की आवश्यकता होती है जिन्हें मैं बनाना और लोड करना चाहता हूं। क्या ऐसी कोई तकनीक है जो मुझे प्रत्येक एक्सटेंशन को एक अलग फ़ाइल में पंजीकृत करने देती है?एक सी ++ कक्षा पंजीकृत करें ताकि बाद में एक फ़ंक्शन सभी पंजीकृत वर्गों पर पुन: सक्रिय हो सके

अद्यतन:

मुझे विश्वास है, स्थिति की मेरी व्याख्या बहुत अस्पष्ट था, इसलिए मैं इसे और अधिक विशिष्ट बनाने का फैसला किया।

मैं विस्तार प्रकारों का संग्रह परिभाषित करना चाहता हूं। प्रत्येक एक्सटेंशन प्रकार के लिए एक्सटेंशन की कोई भी संख्या हो सकती है। रनटाइम के दौरान प्रोग्राम बाहरी पुस्तकालय लोड करता है, एंट्री पॉइंट फ़ंक्शन को हल करता है, इसे कॉल करता है और परिणामस्वरूप, पॉइंटर प्राप्त करता है। फिर यह उस सूचक को सभी पंजीकृत एक्सटेंशन प्रकारों में डालने का प्रयास करता है (dynamic_cast का उपयोग करके, इसलिए एक्सटेंशन प्रकारों के लिए कक्षाएं सभी पॉलिमॉर्फिक बेस क्लास से प्राप्त होती हैं)। यदि कुछ एक्सटेंशन प्रकार का कलाकार सफल होता है, तो उस एक्सटेंशन प्रकार के लिए विशेष हैंडलर को कॉल में जाली पॉइंटर का उपयोग किया जाता है।

विस्तार प्रकारों की संख्या संकलन समय पर ज्ञात है (जबकि जाहिर है, एक्सटेंशन की संख्या अनंत है)। मेरे एप्रोच का उपयोग करके लोडर क्लास इस ज्ञान का उपयोग यह जांचने के लिए करता है कि क्या प्रत्येक एक्सटेंशन प्रकार के लिए हैंडलर मौजूद है (यदि नहीं, प्रोग्राम संकलित नहीं होता है)। इसके अलावा, मेरा अपवाद विस्तार प्रकारों के लिए कक्षाओं को लोडर के बारे में कुछ भी नहीं जानता है (इसलिए लोडर को संशोधित करना आसान है)। लेकिन यदि प्रत्येक एक्सटेंशन प्रकार स्वयं पंजीकृत होता है तो यह अधिक सुविधाजनक होगा।

+0

हेडर एक स्वीकार्य समाधान उत्पन्न कर रहा है? – Arpegius

उत्तर

0

जैसा कि यह पता चला है कि मैं क्या चाहता हूं असंभव है। इसका संदर्भ इस संदर्भ में "रजिस्टर" का अर्थ है "टाइप टाइप प्रकार के अनुक्रम को टाइप करें" और टाइप अनुक्रम अपरिवर्तनीय हैं क्योंकि वे स्वयं प्रकार हैं। तो किसी को या तो इस प्रकार के अनुक्रम मैन्युअल रूप से बनाना चाहिए, या कुछ लोगों ने सुझाव दिया कि "पंजीकरण" रनटाइम में स्थानांतरित करें।

0

अमूर्त फैक्ट्री पैटर्न का उपयोग करके इस तरह के एक विस्तार ढांचे को लागू करना मुश्किल नहीं है।

http://en.wikipedia.org/wiki/Abstract_factory_pattern

आप उन सार कारखाने कार्य/एक वैश्विक सूची में वस्तुओं रजिस्टर, और जो आप उस पर आधार क्या करना चाहते हैं कर सकते हैं।

8

आप अपने सभी वर्गों को किसी प्रकार के संग्रह में स्वयं पंजीकरण कर सकते हैं।

Base.hpp:

#include <memory> 
#include <unordered_map> 
#include <string> 

struct Base 
{ 
    virtual ~Base() = default; 

    using create_f = std::unique_ptr<Base>(); 

    static void registrate(std::string const & name, create_f * fp) 
    { 
     registry()[name] = fp; 
    } 

    static std::unique_ptr<Base> instantiate(std::string const & name) 
    { 
     auto it = registry().find(name); 
     return it == registry().end() ? nullptr : (it->second)(); 
    } 

    template <typename D> 
    struct Registrar 
    { 
     explicit Registrar(std::string const & name) 
     { 
      Base::registrate(name, &D::create); 
     } 
     // make non-copyable, etc. 
    }; 

private: 
    static std::unordered_map<std::string, create_f *> & registry(); 
}; 

Base.cpp:

#include "Base.hpp" 

std::unordered_map<std::string, Base::create_f *> & Base::registry() 
{ 
    static std::unordered_map<std::string, Base::create_f *> impl; 
    return impl; 
} 

अब एक ग्राहक में इस का उपयोग करने के लिए:

व्युत्पन्न यहाँ एक कंकाल तरीका है। एचपीपी:

#include "Base.hpp" 

struct Derived : Base 
{ 
    static std::unique_ptr<Base> create() { return std::make_unique<Derived>(); } 
    // ... 
}; 

Derived.cpp:

#include "Derived.hpp" 

namespace 
{ 
    Base::Registrar<Derived> registrar("MyClass"); 
} 

Base::Registrar<Derived> के निर्माता नाम "MyClass" के तहत वर्ग Derived पंजीकरण की देखभाल करता है।आप गतिशील रूप से के माध्यम से Derived का उदाहरण बना सकते हैं:

std::unique_ptr<Base> p = Base::instantiate("MyClass"); 

कोड/दोहराने पंजीकरण का पता लगाने, उपलब्ध कक्षाओं की एक सूची मुद्रण, आदि ध्यान दें कि कैसे हम किसी भी स्थिर आरंभीकरण आदेश समस्याओं मेरे वास्तविक बनाने से बचने के द्वारा सुधार किया जाना चाहिए सकता है रजिस्ट्री मानचित्र ऑब्जेक्ट एक ब्लॉक-स्टेटिक ऑब्जेक्ट है, जिसे इसकी पहली उपयोग से पहले प्रारंभ करने की गारंटी है, और इस प्रकार इसके अंतिम उपयोग के बाद ही नष्ट हो जाता है।

+0

मैंने ऐसा कुछ माना, लेकिन मुझे संकलन-समय में अधिक दिलचस्पी है। मुझे यकीन नहीं है कि एक मौजूद है, लेकिन फिर भी, सी ++ टेम्पलेट्स की भूमि चमत्कार से भरा है। – grisumbras

+0

कोई स्थिर नहीं है। आप वर्गों को स्वयं पंजीकृत नहीं कर सकते हैं, क्योंकि प्रत्येक कार्यान्वयन फ़ाइल में इसकी स्वयं की संकलन इकाई होती है, और प्रत्येक को अलग-अलग लाइब्रेरी में रखा जा सकता है। इस समाधान की शक्ति यह है कि जब आप एक गतिशील पुस्तकालय लोड करते हैं, तो विस्तार वर्ग स्वचालित रूप से उपलब्ध हो जाता है। यह अच्छी तरह से जाना जाता है और बहुत उपयोगी पैटर्न है। – Arpegius

+0

यह एक बहुत अच्छा कार्यान्वयन है। एकमात्र चीज जिसे मैं समझ नहीं पा रहा हूं वह स्थिर बनावट() ​​फ़ंक्शन पर = 0 है। जहां तक ​​मुझे पता है कि यह अमान्य सी ++ है क्योंकि स्थैतिक कार्य कभी भी आभासी नहीं हो सकते हैं। उस भाग को कैसे काम करना चाहिए? – Shenjoku

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

  • कोई संबंधित समस्या नहीं^_^