如何将公共接口的子集公开给类

时间:2010-11-03 06:49:18

标签: c++ oop

我有一个班级 - 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 个答案:

答案 0 :(得分:2)

在OP有代码段之前的响应

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

以下是我猜你所说的......(只是示例说明代码)

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

答案 1 :(得分:1)

将功能移出PluginLoader

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

干杯&amp;第h。,

答案 2 :(得分:1)

假设您的PluginLoader接口不仅包含Register...方法,并且您希望通过该接口操作加载器,而是在插件和加载器之间提供单独的通信通道,您只需创建另一个接口{也许,{1}}会有公共PluginRegistra方法。

在插件加载器中私有地继承它,并在加载器中将Register...方法实现为私有函数。没有人可以通过插件类访问Register...方法,他们需要通过Register...接口访问它们,只有加载器可以将自身转换为该类型,因为继承是私有的。

现在只需将加载程序传递给插件,就像现在一样;插件的PluginRegistra方法现在采用Load()接口。不需要友谊。由于私有继承,只有插件加载器可以将其自身作为PluginRegistra的实例。

一个例子,根据要求,注意这没有看到编译器。

PluginRegistra