2010-11-03 34 views
3

我有一个类 - 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 

这给我们带来了一圈。还是有什么我失踪?

回答

1

但在插件和加载器之间提供单独的通信通道,您可以简单地创建另一个接口,也许它将具有公共方法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*) 
     { 
     } 
} 
+0

漂亮做作:)。你能提供一个代码示例吗? – nakiya 2010-11-03 09:14:26

+0

任何人都可以向我详细解释这一点吗? :(我试图做它看起来像在要求我做什么没有结果 – nakiya 2010-11-03 09:41:16

+0

它根本没有作出任何设计从逻辑上说,你有两个单独的接口到你的插件加载器,它暴露在插件允许自己的接口注册以及它暴露给世界的界面,所以这样实现它。 – 2010-11-03 09:55:26

1

将函数从PluginLoader中移出。

编辑:考虑到问题的模糊性,我应该提及您可以通过传递一个提供函数的对象来传递一堆相关函数作为参数。你可以从提供函数的类继承。等等。

干杯&心连心,

2

响应的OP有过的代码片断

我看不出这个问题与你指出的朋友。两个抽象类可以是彼此的朋友。它绝对没有问题。

这里是我猜你是说明假设你PluginLoader接口包含的不仅仅是Register...方法更多,你想通过这个接口来操作装载机...(只是一个样本illustratory代码)

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

你的例子现在工作。但是当你从'Plugin'和'PluginInfo'派生时会发生什么? – nakiya 2010-11-03 07:14:41

+0

@nakiya:这不是问题。请参阅更新代码 – Chubsdad 2010-11-03 07:18:04

+0

顺便说一句,我认为你的意思是PluginLoader而不是PluginINfo? – Chubsdad 2010-11-03 07:21:43

相关问题