我有一个关于在C++库中隐藏接口(interface)详细信息的问题。以下示例说明了该问题:
假设w有一个名为 ISystem 的类,它公开了Init,Run,Tick,Shutdown,GetXXXSubSystem等方法。
X是各种接口(interface)的指针,例如:ISoundSystem,IInputSystem
我们也有ISystem的具体实现,例如:
Win32System,OSXSystem 等。
这些特定的实现使用pimpl习惯用法来隐藏内部结构
例如Win32System实例化 Win32RawInputSystem
担任输入系统经理。
所有这些管理器都具有自己的Init,Run,Tick和Shutdown方法
它们不是接口(interface)的一部分(仅是具体的实现),它们是由具体的系统实现运行和管理的。
调用GetXXXSubSystem的用户获取的接口(interface)指针没有这些方法(Init等),但是
仍然他可以把他的指针投向具体的实现
并触发他不应该访问的方法,例如Init Run Tick等。
问题是,是否可以以某种方式隐藏具体的类(class)?我试图做那些方法
在具体的实现中受到保护,并在类型上将类最终作为模板,但最终似乎是 friend ,但这似乎很容易,并且现有的hack无法在VC11中使用。
我认为正确的唯一方法是从 header 转移具体的实现声明
放入Win32System类的cpp文件中,但是我看到这样做的巨大缺点(即使不确定这样做是否可行),因为这样每个子系统
也必须是此cpp文件的一部分,这将成为可维护性的噩梦。
我正在考虑的另一个解决方案是使用工厂方法
(RawInput.h)
IInputSystem* CreateRawInputSystem();
(RawInput.cpp)
class RawInput : public IInputSystem {}; ...
并将类的定义移动到cpp文件,但是,如何从库的其他部分(即Win32System impl)访问这种类型?
是否可以从其他.cpp文件中包含.cpp文件?
在此先感谢您提供任何提示。
最佳答案
如果要在此处开发库,则可以选择不导出不想公开的具体类的头文件。您不能转换为没有定义的类。
范例:
MyProjectFolder / Src / Export / ISystem.h
#ifndef ISYSTEM_H
#define ISYSTEM_H
#include "IInputSystem.h"
class ISystem
{
public:
virtual ~ISystem() {};
virtual void Run()=0;
virtual IInputSystem* GetInputSystem()=0;
};
#endif
MyProjectFolder / Src / Export / IInputSystem.h
#ifndef IINPUTSYSTEM_H
#define IINPUTSYSTEM_H
class IInputSystem
{
public:
virtual ~IInputSystem() {};
virtual void Foo()=0;
virtual void Bar()=0;
};
#endif
MyProjectFolder / Src / Export / Win32System.h
#ifndef WIN32SYSTEM_H
#define WIN32SYSTEM_H
#include "ISystem.h"
class Win32System : public ISystem
{
public:
Win32System();
virtual void Run();
virtual IInputSystem* GetInputSystem();
private:
struct impl;
impl* m_pImpl;
};
#endif
MyProjectFolder / Src / Win32RawInputSystem.h
#ifndef WIN32RAWINPUTSYSTEM_H
#define WIN32RAWINPUTSYSTEM_H
#include "IInputSystem.h"
class Win32RawInputSystem : public IInputSystem
{
public:
virtual void Foo();
virtual void Bar();
virtual void Run(); // you do not want to expose that function
};
#endif
MyProjectFolder / Src / Win32System.cpp
#include "Win32System.h"
#include "Win32RawInputSystem.h"
struct Win32System::impl
{
Win32RawInputSystem inputSys;
};
Win32System::Win32System()
: m_pImpl(new impl)
{
}
void Win32System::Run()
{ // run run run
}
IInputSystem* Win32System::GetInputSystem()
{
return &m_pImpl->inputSys;
}
因此,在构建项目时,其包含搜索路径不仅是Src /,而且是Src / Export /。在您的库项目中,您可以使用所有类,包括Win32RawInputSystem。部署库时,您仅放弃驻留在Src / Export /文件夹中的 header 。客户端仍然可以使用该库,但是他们永远不能将
IInputSystem*
转换为Win32RawInputSystem*
,因为它们没有该 header 。因此,该库的用户可以在Foo()
上调用Bar()
和IInputSystem*
,但他们永远无法调用Run()
。关于c++ - 接口(interface),隐藏C++中的具体实现细节,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12331752/