防止公共使用用作私有基类的类

时间:2017-11-30 14:18:02

标签: c++ inheritance private

如何确保只有“我的”代码可以使用类,即使它是使用 base 类? (如果它不用作基类,我可以将它作为我的一个类的privateprotected嵌套类)

如果我想表明为我的一个类使用基类只是一个实现细节,我可以使用私有基类:

 class Base
 {
      ...
 }

 class Derived: private Base
 {
 public:

      Derived(...): Base{...} {... };

      ...
 }

对于Derived课程的客户,我使用Base课程并不明显:

 #include "Derived.h"

 void client() {
    Derived d{...};
    Base *b = static_cast< Base * >(&d);// error
    ...
 }

但是想象一下Base类是如此专业,或者令人困惑或者难以使用,我不希望我的代码的客户端可以将它用作基类或创建对象那个班。在某种意义上,我希望它对我的一些代码是“私有的”,所以这样的客户端代码失败了:

 #include "Derived.h"

 class Client: Base// error wanted here
 {
 public:
    Client(...): Base{...} {...};

    ...
 }

 void client()
 {
    Derived d{...};// OK
    Base b{...};// error wanted here
    Client c{...};// error wanted here
 }

我该怎么做?

实际上,我问我怎样才能实现像Java's package-private classes这样的东西,只能在同一个“包”(模块)中的其他类访问,但不能被“package”之外的代码使用

3 个答案:

答案 0 :(得分:3)

您可以通过将“私有”实体放入detail命名空间来按惯例“强制执行”此操作。许多流行的库(例如Boost)执行此操作:

namespace detail
{
    class Base { /* ... */ };
}

class Derived : private detail::Base
{
    /* ... */
};

当模块被标准化时,这个问题将得到妥善解决,因为您将能够控制哪些实体被导出以及哪些是实现细节。

答案 1 :(得分:2)

这不能像在Java中那样直接完成。如果只是避免混淆的问题,您可以将Base移动到名称空间中,该名称空间应被代码的客户端忽略,例如:

namespace hidden {
  class Base {
    ..
  };
}

class Derived : private hidden::Base {
  ...
};

如果您真的想避免使用Base的可能性,那么如果您计划将Base用作多个类的父级(这个数量可能会有所不同),那么这是一个相当困难的故事随着时间的推移)。您可以给Base private构造函数,并指出每个派生类都是friend Base

class Hider {
  private:
    Hider() = delete;
    class Base {
      ..
    };

  friend class Derived;
};

class Derived : Hider::Base {
  ..
};

当然,这需要您希望从Base派生的每个新课程进行手动维护。

答案 2 :(得分:1)

如果你想100%强制执行它,并且不喜欢“请不要使用以'_'开头的东西”的python方法,那么我相信这是你的停靠点:

class Dave;

class MyPrivateBaseClasses {
  private:
    MyPrivateBaseClasses();    // ensure nothing can use this class
    class BaseClassA {};

    friend Dave;
};

class Dave : public/private MyPrivateBaseClasses::BaseClassA
{};

当然 - 这意味着你必须与想要使用它的所有东西交朋友,但它确实能为你提供你想要的东西;使用BaseClassA对人们提供100%的保护。