如何在C++中隐藏一个类?

10

假设我有两个类想要在给定的头文件中可见,并且有一个是它们的祖先类,我希望这个祖先类只对之前提到的两个类可见。我如何实现这样的“不可见”类功能在C++中?


12
为什么?只需将其抽象化,以便不能实例化但可用作接口。这很有用。 - Lightness Races in Orbit
3
你可以为它们设置命名空间,但我相信你无法使它们完全不可访问。 - obmarg
3
与其将该类作为祖先类,你可以将它作为一个“被包含的”类,并使用私有实现。http://www.drdobbs.com/cpp/making-pimpl-easy/205918714 - Josh Greifer
6
如果他在问如何做,那么这也关乎我们的事业 :) - Lightness Races in Orbit
1
@obmarg:我也会这样说。 即使命名空间不 真正 使类无法访问也无所谓。 如果您在诸如namespace implementationnamespace detail之类的东西中有一个类,某些人因为技术上可能而感到有必要使用它,那就是他自己的问题。 您已经清楚地表达了意图,这才是最重要的。 如果他们在滥用您明确声明的意图之后崩溃并烧毁,并且他们来抱怨,只需告诉他们走开。 - Damon
显示剩余11条评论
4个回答

11

滥用 class 作为 namespace 的替代方案会导致这种情况。我不建议使用此模式。

class hidden_stuff {
private: // hide base from everyone
    struct base {
        // contents
    };
public:
    class derived1;
};
typedef class hidden_stuff::derived1 derived1;

class hidden_stuff::derived1
    : private hidden_stuff::base {}; // private inheritance required
            // or hidden_stuff::base is accessible as derived1::base

真正的解决方案(虽然不是技术上满足问题的)

更好的解决方案是使用一个明确命名的namespace,如impl::detail::,这将向用户传达不能使用其中任何类,并防止可能的重载等不良影响。这就是大多数库(即使标准库实现)如何“隐藏”类。


1
我有点惊讶地发现我们不能使用未命名的命名空间来隐藏头文件中的类。它似乎是完美的工具(除了不允许使用)。 - jww
我喜欢将其分成单独的命名空间。 - vincenzopalazzo

9

这是不可能的。

C++要求在使用类作为基类时必须完整定义,而由于其包含机制,在类定义的地方完全定义的任何内容都必须对所有能够看到该类定义的人可见。

C++有机制来防范Murphy(意外),但无法防范Machiavelli(黑客)。


话虽如此,这个目的本身就是可疑的,我唯一能想到的理由就是防止用户依赖于你的Derived类从这个Fantom基类派生的事实。好吧,私有派生:class Derived: private Fantom {};或者使用组合:class Derived { private: Fantom _fantom; };都可以实现这一点。


2

我建议不要隐藏类,而是禁用它。例如:

class Hidden
{
  private:
    friend class Exposed;
    Hidden() {}
    int hidden_x;
};

class Exposed : private Hidden
{
  public:
    Exposed() : Hidden() {}
    void DoStuff() { printf( "%d" , hidden_x ); }
};

因此,您可以: - 在您的代码中创建任意数量的公开类实例 - 从这些实例调用DoStuff()方法

但是您不能: - 实例化隐藏类(私有构造函数) - 直接或通过公开类操作隐藏类成员(它们是私有的)


0
一个匿名回答的变体,与私有继承不同,您可以添加隐藏类的私有成员。
class Hidden
{
   private:
      friend class Exposed;
      Hidden() {}
      int hidden_x;
};

class Exposed
{
  public:
      Exposed() {}
      void DoStuff() { printf( "%d" , hidden.hidden_x ); }
  private:
      Hidden hidden_;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接