How to open a subset of an open interface for a class

I have a class - PluginLoader , which deals with another Plugin class to perform its functions. Plugin class uses some functions in the PluginLoader . Both of these classes are abstract base classes, so I cannot declare Plugin as a friend of PluginLoader . And I don’t want the Plugin functions to be available in the public PluginLoader interface, because they are not related to the PluginLoader user. Is this a common problem? How to solve it?

EDIT: Code Example

 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); } } 

Although I want RegisterPlugin be available for the Plugin class, it makes no sense to leave it visible to other users of the PluginLoader class.

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(); } 

This causes a compiler error:

 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 

Which brings us a full circle. Or am I missing something?

+3
c ++ design oop
source share
3 answers

Assuming that your PluginLoader interface contains more than just Register... methods Register... and that you want to control the bootloaders through this interface, but provide a separate communication channel between the plugin and the bootloader, you can simply create another PluginRegistra interface, possibly on which Register... methods are publicly available.

Inherit the loader from it in its plugin and implement Register... methods as private functions in the loader. No one can access the Register... methods Register... through the plugin class, they need to access them through the PluginRegistra interface, and only the loader can convert itself to this type, since inheritance is private.

Now just pass the bootloader to the plugin in exactly the same way as now; now the plugin module Load() has a PluginRegistra interface. Friendship is not needed. Only a downloader plugin can impersonate an instance of PluginRegistra due to private inheritance.

As an example, as requested, note that this was not seen by the compiler.

 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
source share

Answer Before OP had a code snippet

I do not see the problem with the friends you indicate. Two abstract classes can be each other's friends. There is no problem.

Here is what I assume you are specifying ... (just an example of illustrative code)

 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
source share

Move functions from PluginLoader .

EDIT : given the vagueness of the question, I should mention that you can pass a bunch of related functions as an argument by passing an object that provides functions. And you can inherit from a class that provides functions. And so on.

Cheers and hth.,

+1
source share

All Articles