C++ 如何向类公开公共接口的子集
我有一个类-C++ 如何向类公开公共接口的子集,c++,oop,C++,Oop,我有一个类-PluginLoader,它处理另一个类Plugin来执行它的功能Plugin类使用了PluginLoader中的一些函数。这两个类都是抽象基类,所以我不能将Plugin声明为pluginload的朋友。我不希望PluginLoader的公共界面中有PluginLoader使用的函数,因为它们与PluginLoader的用户没有关联。这是一个普遍的问题吗?如何解决 编辑:代码示例 class PluginLoader { public: virtual void R
PluginLoader
,它处理另一个类Plugin
来执行它的功能Plugin
类使用了PluginLoader
中的一些函数。这两个类都是抽象基类,所以我不能将Plugin
声明为pluginload
的朋友。我不希望PluginLoader
的公共界面中有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
类的其他用户看到它
编辑2:@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();
}
这给我们带来了一个完整的循环。或者我缺少了什么?将函数移出
插件加载程序
编辑:鉴于问题的模糊性,我或许应该提到,通过传递提供函数的对象,可以将一组相关函数作为参数传递。您可以从提供函数的类继承。等等
干杯&hth.,在OP有代码片段之前的响应
我看不出你指出的朋友之间的问题。两个抽象类可以是彼此的朋友。这绝对没有问题
以下是我猜您所指的…(只是一个示例插图代码)
假设您的PluginLoader
接口包含的不仅仅是Register…
方法,并且您希望通过该接口操作加载程序,但在插件和加载程序之间提供一个单独的通信通道,那么您可以简单地创建另一个接口,PluginRegistra
,它将有公共注册…
方法
在插件加载程序中以私有方式继承它,并在加载程序中将Register…
方法作为私有函数实现。没有人可以通过plugin类访问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*)
{
}
}
你的例子现在起作用了。但是当你从插件
和插件信息
派生时会发生什么?顺便说一句,我想你指的是插件加载程序而不是插件信息?嗯,所以朋友
完全是一种编译时机制…:(.为什么我没想到?是的。抽象类不能实例化。就是这样。它不会影响友谊机制,如插图所示。有人能详细解释一下吗?:(.我试图做它要求我做的事情,但没有结果。这根本不是人为的。从逻辑上讲,你的插件加载器有两个独立的接口,一个是它向插件公开以允许它们注册的接口,另一个是它向世界公开的接口,所以就这样实现它。@Len Holgate:明白了。谢谢。顺便说一句,PluginLoader
应该继承IRegisterPlugins
中的protected
。否则你不能将这个作为IRegisterPlugins
传递给函数。我认为私有继承应该可以工作鉴于上面的示例,如果你让这两个接口继承,我想你需要保护。
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);
}
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*)
{
}
}