这个问题困扰了我一段时间,但找不到处理它的最佳方法。我试图通过一个例子来证明这一点。
我正在开发一个包含许多类的图形库。有些类是“ ”的一部分关系,就像这三个类一样:
namespace MyGraphicsLibrary
{
class MatrixStack
{
};
class Transform
{
MatrixStack mMatrixStack;
};
class Renderer
{
Transform mTransform;
};
}
Renderer
类供用户使用,但我不希望他们在查找Transform
时看到MatrixStack
,MyGraphicsLibrary
类。最后两个类仅适用于Renderer
类,不适合用户使用。
我在这里尝试做两件事:
隐藏用户的Transform
,MatrixStack
课程。
反映班级的“部分”层次结构。
我尝试了以下解决方法:
对我来说,最好的解决方案是私有嵌套类,因为它会向用户显示嵌套类是私有的,如果只是查看Renderer
类声明,也会反映层次结构。以下帖子实际上让我不确定这是一个好的解决方案:Pros and cons of using nested C++ classes and enumerations?
我尝试将Transform
,MatrixStack
放入另一个名为Private
的命名空间中。因此,查找MyGraphicsLibrary
命名空间的用户将看到Private
命名空间仅覆盖所有不适合用户的类。
这很好,但是有很多其他类都有相同的问题,我很快就用Private
命名空间填充了彼此无关的类。
在这里,我只能提出丑陋的解决方案,比如引入嵌套的命名空间:
namespace MyGraphicsLibrary
{
//private classes belonging to Renderer class
namespace PrivateRenderer
{
class MatrixStack
{
};
class Transform
{
MatrixStack mMatrixStack;
};
}
//public classes for users
class Renderer
{
Transform mTransform;
};
}
也许我在这里想念一些东西,但你觉得哪一个是要走的路。 有没有人有第三种方式?
答案 0 :(得分:2)
你可以使用PIMPL-(也称为不透明指针)习语。 戴上帽子,您可以通过以下方式完全隐藏用户的类:
在您的公开标题中(在您的包含文件夹中): Renderer.h
class RendererImpl; // forward declaration of internal render structure
//public classes for users
class Renderer
{
public:
Renderer();
~Renderer();
// public interface comes here and delegates all calls to RendererImpl (have to be implemented in cpp)
RendererImpl* renderer; // better use something like QScopedPointer here
};
cpp:
#include "RendererImpl.h" // your actual renderer that
Renderer::Renderer()
:renderer(new RendererImpl)
{}
Renderer::~Renderer()
{
delete renderer;
}
可以从API完全隐藏实现。标头必须与真实接口分开。
答案 1 :(得分:1)
如果要将Transform存储为普通(非指针/引用)成员,那么对于公共头的编译,其定义也应该是可见的,因为它会影响容器类的布局。
因此,只要您想使用容器类,该类型就会显示。
您有以下选择:
未命名的命名空间:在标题中绝对是个坏主意。未命名的命名空间类似于C static:它们获得编译器生成的标识符,该标识符保证对于给定的转换单元是唯一的。您最终将获得与您定义的许多不同地方一样多的不同变换类型。
答案 2 :(得分:0)
使用匿名命名空间:
namespace MyGraphicsLibrary
{
namespace
{
class MatrixStack
{
};
class Transform
{
MatrixStack mMatrixStack;
};
}
class Renderer
{
Transform mTransform;
};
}