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

Posted

技术标签:

【中文标题】如何在 C++ 中隐藏一个类?【英文标题】:How can I hide a class in C++? 【发布时间】:2012-12-15 02:06:43 【问题描述】:

假设我有 2 个我希望可见的类(在给定的头文件中)和一个作为其祖先的类,我希望仅对前面提到的两个类可见。如何实现这种在 C++ 中不可见的类功能?

【问题讨论】:

为什么?只需将其抽象化,这样它就不能被实例化,而是用作接口。这有用 你可以命名它们,但我很确定你不能让它们完全无法访问 与其将类设为祖先,不如将其设为包含类,并使用私有实现drdobbs.com/cpp/making-pimpl-easy/205918714 如果他问怎么做,这也是我们的事:) @obmarg:我也是这么说的。被命名空间不会真正 使类不可访问甚至都没有关系。如果您有类似namespace implementationnamespace detail 的课程,并且有些混蛋觉得无论如何都不得不使用它,只是因为它在技术上是可行的,那是他自己的问题。你已经明确了意图,这才是最重要的。如果在他们滥用您明确说明的意图后它崩溃并燃烧,并且他们来抱怨,请告诉他们...关闭。 【参考方案1】:

匿名答案的变体,您可以添加隐藏类的私有成员,而不是私有继承。

class Hidden

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

class Exposed

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

【讨论】:

【参考方案2】:

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

class Hidden

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

class Exposed : private Hidden

  public:
    Exposed() : Hidden() 
    void DoStuff()  printf( "%d" , hidden_x ); 
;

所以你可以: - 在您的代码中创建任意数量的 Exposed 类实例 - 从这些实例调用 DoStuff() 方法

但你不能: - 实例化隐藏类(私有构造函数) - 直接或通过 Exposed 类对 Hidden 类成员进行操作(它们是私有的)

【讨论】:

【参考方案3】:

滥用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::,这将向用户传达他们不应该在内部使用任何类,并停止对重载的任何可能的不良影响之类的。这就是大多数库(甚至标准库实现)对用户“隐藏”类的方式。

【讨论】:

得知我们不能使用未命名的命名空间来隐藏头文件中的类时,我感到有点惊讶。这似乎是一个完美的工具(除了不允许)。 我喜欢细分成单独的命名空间【参考方案4】:

这是不可能的。

C++ 要求一个类在它被用作基础时被完全定义,并且由于它的包含机制,任何在类定义时完全定义的东西都必须对所有可以看到定义的人可见所述类。

C++ 具有防止墨菲(事故)但不能防止马基雅维利(黑客)的机制。


话虽如此,目的本身是可疑的,我能理解的唯一原因是防止用户依赖您的 Derived 类派生自这个 Fantom 基础这一事实。好吧,私下派生:class Derived: private Fantom ; 或使用组合代替 class Derived private: Fantom _fantom; ; 都可以实现这一点。

【讨论】:

以上是关于如何在 C++ 中隐藏一个类?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 静态库中隐藏符号?

如何在 C++ 中模拟覆盖父函数(不隐藏)?

如何在 C++ 共享库中隐藏业务对象的实现细节并提供接口

C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?

C++中,一个类,究竟有多少隐藏的默认函数?

如何在 C++ 中使用 Windows API 隐藏桌面图标?