मेरे पास एक वर्ग है - PluginLoader जो अपने कार्यों को करने के लिए एक अन्य वर्ग Plugin से संबंधित है। Plugin वर्ग PluginLoader में कुछ फ़ंक्शन का उपयोग करता है। ये दोनों वर्ग अमूर्त आधार वर्ग हैं इसलिए मैं Plugin को PluginLoader के मित्र के रूप में घोषित नहीं कर सकता। और मैं नहीं चाहता कि Plugin का उपयोग PluginLoader के सार्वजनिक इंटरफ़ेस में उपलब्ध हो क्योंकि PluginLoader के उपयोगकर्ता के लिए उनकी कोई प्रासंगिकता नहीं है। क्या यह एक आम समस्या है? इसे कैसे हल करें?

संपादित करें: कोड उदाहरण

class PluginLoader
{
   public:
      virtual void RegisterPlugin(Plugin*) = 0;
      virtual void RegisterFunction(int, Plugin*) = 0;
};

class Plugin
{
   public:
      virtual void Load(PluginLoader&) = 0;
}

class PlugImp : public Plugin
{
   public:
      virtual void Load(PluginLoader& oPLoader)
      {
         //Do stuff
         oPLoader.RegisterPlugin(this);
      }
}

हालांकि मैं चाहता हूं कि RegisterPlugin Plugin वर्ग के लिए उपलब्ध हो, फिर भी इसे PluginLoader वर्ग के अन्य उपयोगकर्ताओं के लिए दृश्यमान छोड़ने का कोई मतलब नहीं है।

EDIT2: @chubsdad

#include <iostream>

using namespace std;

class PluginLoader;
class Plugin
{
    public:
        virtual void Register(PluginLoader&) = 0;
        virtual ~Plugin() = 0;
};

class PluginLoader
{
    public:
        virtual void Load() = 0;

        virtual ~PluginLoader() = 0;

    private:
        friend class Plugin;
        virtual void RegisterPlugin(Plugin&) = 0;
};

class PluginImp : public Plugin
{
    public:
        void Register(PluginLoader& oPLoader)
        {
            oPLoader.RegisterPlugin(*this);
        }
};

class PluginLoaderImp : public PluginLoader
{
    public:
        void Load()
        {
            Plugin* pP = new PluginImp();
            pP->Register(*this);
        }

    private:
        void RegisterPlugin(Plugin& oP)
        {
            cout << "PluginLoaderImp::RegisterPlugin" << endl;
        }
};

int main()
{
    PluginLoader* pPLoader = new PluginLoaderImp();
    pPLoader->Load();
}

यह संकलक त्रुटि फेंकता है:

main.cpp: In member function ‘virtual void PluginImp::Register(PluginLoader&)’:
main.cpp:22: error: ‘virtual void PluginLoader::RegisterPlugin(Plugin&)’ is private
main.cpp:30: error: within this context

जो हमें पूर्ण चक्र लाता है। या कुछ ऐसा है जो मुझे याद आ रहा है?

3
nakiya 3 नवम्बर 2010, 09:49

3 जवाब

सबसे बढ़िया उत्तर

यह मानते हुए कि आपके PluginLoader इंटरफ़ेस में केवल Register... विधियां नहीं हैं और आप उस इंटरफ़ेस के माध्यम से लोडर में हेरफेर करना चाहते हैं, लेकिन प्लगइन और लोडर के बीच एक अलग संचार चैनल प्रदान करते हैं, आप बस एक और इंटरफ़ेस बना सकते हैं, PluginRegistra, शायद, जिस पर सार्वजनिक Register... विधियां होंगी।

अपने प्लगइन लोडर में इससे निजी तौर पर इनहेरिट करें और लोडर में निजी कार्यों के रूप में Register... विधियों को लागू करें। प्लगइन वर्ग के माध्यम से कोई भी Register... विधियों तक नहीं पहुंच सकता है, उन्हें उन्हें PluginRegistra इंटरफ़ेस के माध्यम से एक्सेस करने की आवश्यकता है और केवल लोडर स्वयं को उस प्रकार में परिवर्तित कर सकता है क्योंकि विरासत निजी है।

अब बस लोडर को प्लगइन में ठीक उसी तरह पास करें जैसे आप अभी करते हैं; प्लगइन की Load() विधि अब एक PluginRegistra इंटरफ़ेस लेती है। दोस्ती की जरूरत नहीं। निजी विरासत के कारण केवल प्लगइन लोडर PluginRegistra के उदाहरण के रूप में स्वयं को सौंप सकता है।

एक उदाहरण, जैसा अनुरोध किया गया है, ध्यान दें कि यह एक कंपाइलर नहीं देखा है।

class PluginLoader
{
   public: 
      virtual void LoadPlugin(Plugin*) = 0;
};

class PluginRegistra
{
   public:
      virtual void RegisterPlugin(Plugin*) = 0;
      virtual void RegisterFunction(int, Plugin*) = 0;
};

class Plugin
{
   public:
      virtual void Load(PluginRegistra&) = 0;
}

class PlugImp : public Plugin
{
   public:
      virtual void Load(PluginRegistra& oPLoader)
      {
         //Do stuff
         oPLoader.RegisterPlugin(this);
      }
}

class LoaderImp : public PluginLoader : private PluginRegistra
{
   public :
      virtual void LoadPlugin(Plugin* plugin)
      {
         plugin.Load(this);
      } 

   private :

      virtual void RegisterPlugin(Plugin*) 
      {
      }

      virtual void RegisterFunction(int, Plugin*)
      {
      }
}
1
Len Holgate 3 नवम्बर 2010, 13:22
क्या कोई मुझे इस बारे में विस्तार से बता सकता है? :(। मैंने वह करने की कोशिश की जो ऐसा लगता है कि यह मुझे बिना किसी परिणाम के करने के लिए कहता है।
 – 
nakiya
3 नवम्बर 2010, 12:41
यह कतई कल्पित नहीं है। तार्किक रूप से, आपके पास अपने प्लगइन लोडर के लिए दो अलग-अलग इंटरफेस हैं, वह इंटरफ़ेस जो इसे प्लगइन्स के सामने खुद को पंजीकृत करने की अनुमति देता है और इंटरफ़ेस जिसे यह दुनिया के सामने उजागर करता है, इसलिए इसे इस तरह लागू करें।
 – 
Len Holgate
3 नवम्बर 2010, 12:55
होल्गेट: समझ गया। धन्यवाद। बीटीडब्ल्यू, PluginLoader को protected से IRegisterPlugins इनहेरिट करना चाहिए। अन्यथा आप this को किसी फ़ंक्शन में IRegisterPlugins के रूप में पास नहीं कर सकते।
 – 
nakiya
3 नवम्बर 2010, 12:59
मुझे लगता है कि निजी विरासत को ऊपर दिए गए उदाहरण को देखते हुए काम करना चाहिए, अगर आपको दो इंटरफेस विरासत में मिले हैं, तो आपको संरक्षित की आवश्यकता होगी, मुझे उम्मीद है।
 – 
Len Holgate
3 नवम्बर 2010, 13:01

ओपी के पास कोड स्निपेट होने से पहले प्रतिक्रिया

मैं उन मित्रों के साथ समस्या नहीं देखता जो आप इंगित कर रहे हैं। दो अमूर्त वर्ग एक दूसरे के मित्र हो सकते हैं। इसमें बिल्कुल कोई मसला नहीं है।

मुझे लगता है कि आप जो संकेत दे रहे हैं वह यहां है...(सिर्फ एक नमूना उदाहरण कोड)

struct pluginloader;

struct plugin{
public:
   void publicm(pluginloader &r);
   virtual ~plugin() = 0;             // abstract
private:
   void privatem(pluginloader &r);    // may be virtual in real code
};

struct pluginloader{
public:
   void publicm(){};
   virtual ~pluginloader() = 0;       // abstract
private:
   void privatem(){}                  // may be virtual in real code
   friend struct plugin;              // friend declaration
};

void plugin::publicm(pluginloader &r){
   r.privatem();                      // use private methods of pluginloader
}

void plugin::privatem(pluginloader &r){
   r.privatem();                      // use private methods of pluginloader
}

plugin::~plugin(){}
pluginloader::~pluginloader(){}

struct APlugin : plugin{
   ~APlugin(){}
};

struct ALoader : pluginloader{
   ~ALoader(){}
};

int main(){
   APlugin apl;
   ALoader ald;

   apl.publicm(ald);
}
2
Chubsdad 3 नवम्बर 2010, 10:23
आपका उदाहरण अभी के लिए काम करता है। लेकिन क्या होता है जब आप Plugin और PluginInfo से व्युत्पन्न होते हैं?
 – 
nakiya
3 नवम्बर 2010, 10:14
बीटीडब्लू, मुझे लगता है कि आपका मतलब प्लगइन लोडर है और प्लगइनइन्फो नहीं?
 – 
Chubsdad
3 नवम्बर 2010, 10:21
हम्म तो friend पूरी तरह से एक कंपाइल-टाइम मैकेनिज्म है... :(। मैंने ऐसा क्यों नहीं सोचा?
 – 
nakiya
3 नवम्बर 2010, 10:23
हां। सार वर्गों को तत्काल नहीं किया जा सकता है। यह बात है। यह सचित्र के रूप में दोस्ती तंत्र को प्रभावित नहीं करता है
 – 
Chubsdad
3 नवम्बर 2010, 10:25

कार्यों को PluginLoader से बाहर ले जाएं।

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

चीयर्स और एचटीएच।,

1
Cheers and hth. - Alf 3 नवम्बर 2010, 10:09