मेरे पास एक वर्ग है - 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 जवाब
यह मानते हुए कि आपके 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*)
{
}
}
ओपी के पास कोड स्निपेट होने से पहले प्रतिक्रिया
मैं उन मित्रों के साथ समस्या नहीं देखता जो आप इंगित कर रहे हैं। दो अमूर्त वर्ग एक दूसरे के मित्र हो सकते हैं। इसमें बिल्कुल कोई मसला नहीं है।
मुझे लगता है कि आप जो संकेत दे रहे हैं वह यहां है...(सिर्फ एक नमूना उदाहरण कोड)
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);
}
Plugin
और PluginInfo
से व्युत्पन्न होते हैं?
friend
पूरी तरह से एक कंपाइल-टाइम मैकेनिज्म है... :(। मैंने ऐसा क्यों नहीं सोचा?
कार्यों को PluginLoader
से बाहर ले जाएं।
संपादित करें: प्रश्न की अस्पष्टता को देखते हुए मुझे शायद यह उल्लेख करना चाहिए कि आप कार्यों को प्रदान करने वाली वस्तु को पारित करके तर्क के रूप में संबंधित कार्यों का एक समूह पारित कर सकते हैं। और आप उस वर्ग से प्राप्त कर सकते हैं जो कार्य प्रदान करता है। और इसी तरह।
चीयर्स और एचटीएच।,
संबंधित सवाल
नए सवाल
c++
C ++ एक सामान्य-प्रयोजन प्रोग्रामिंग भाषा है। यह मूल रूप से C के विस्तार के रूप में डिज़ाइन किया गया था और इसमें एक समान सिंटैक्स है, लेकिन यह अब पूरी तरह से अलग भाषा है। C ++ कंपाइलर के साथ संकलित कोड के बारे में प्रश्नों के लिए इस टैग का उपयोग करें। विशिष्ट मानक संशोधन [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] या [C ++ 23], आदि से संबंधित प्रश्नों के लिए संस्करण-विशिष्ट टैग का उपयोग करें। ।
PluginLoader
कोprotected
सेIRegisterPlugins
इनहेरिट करना चाहिए। अन्यथा आपthis
को किसी फ़ंक्शन मेंIRegisterPlugins
के रूप में पास नहीं कर सकते।