我有一个类-PluginLoader,它处理另一个类Plugin来执行其功能。 Plugin类在PluginLoader中使用一些功能。这两个类都是抽象基类,因此我不能将Plugin声明为PluginLoader的 friend 。而且我不希望Plugin使用的功能在PluginLoader的公共(public)接口(interface)中可用,因为它们与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

这给我们带来了一个完整的圈子。还是我想念的东西?

最佳答案

假设您的PluginLoader接口(interface)包含的不仅是Register...方法,而且您希望通过该接口(interface)操作加载程序,但是要在插件和加载程序之间提供单独的通讯 channel ,则可以简单地创建另一个接口(interface)PluginRegistra,也许可以在其上使用公共(public)Register...方法它。

在插件加载程序中从其私有(private)继承,并在加载程序中将Register...方法实现为私有(private)函数。没有人可以通过plugin类访问Register...方法,他们需要通过PluginRegistra接口(interface)访问它们,并且只有加载程序才能将自身转换为该类型,因为继承是私有(private)的。

现在,只需按照与现在完全相同的方式将加载程序传递给插件即可;插件的Load()方法现在采用PluginRegistra接口(interface)。不需要友谊。由于私有(private)继承,只有插件加载程序可以将自己作为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*)
      {
      }
}

08-06 14:47