c++ - 如何仅将实现公开给 pimpl 习语中的一组指定类?

标签 c++

让我们有一个class A它有一个内部 class A::Impl . class AllowedToAccess应该能够得到 A::Impl&来自 class A ,没有其他类(class)应该能够做到这一点,甚至不知道 class A::Impl存在。

class A_1
{
public:
    class Impl;

    Impl& impl();
    const Impl& impl() const;

private:
    std::unique_ptr<Impl> m_impl;
};

class A_2
{
private:
    friend class AllowedToAccess;

    class Impl;
    std::unique_ptr<Impl> m_impl;
};

class A_3
{
private:
    friend class AllowedToAccess;

    class Impl;

    class ImplContainer
    {
        friend class A_3;
        std::unique_ptr<Impl> impl;
    } m_implContainer;

    Impl& impl(); // return *m_implContainer.impl;
    const Impl& impl() const; // return *m_implContainer.impl;
};

下面是一些代码来说明我的想法。

A_1

优点:m_impl是安全的。

缺点:类不应该知道 A::Impl会知道它(虽然他们不知道 A::Impl 到底是什么)。

A_2

优点:类不应该知道 A::Impl不会知道的。

缺点:m_impl不安全( AllowedToAccess 可能只是将其设置为 nullptr )。

A_3

优点:类不应该知道 A::Impl不会知道它和m_impl是安全的。

缺点:ImplContainer 的样板代码.

有什么更好的主意吗?

编辑:提出了这样的解决方案。

template <typename T>
class Accessor
{
private:
    friend class AllowedToAccess;

    typedef typename T::Impl impl_t;

    static typename T::Impl& impl(T& t)
    {
        return *t.m_impl;
    }

    static const typename T::Impl& impl(const T& t)
    {
        return *t.m_impl;
    }
};

class A
{
private:
    friend class Accessor<A>;

    class Impl;
    std::unique_ptr<Impl> m_impl;
};

class A::Impl
{
public:
    void f() const
    {

    }
};

class AllowedToAccess
{
public:
    AllowedToAccess()
    {
        const A a;

        const Accessor<A>::impl_t& impl = Accessor<A>::impl(a);

        impl.f();
    }
};

有一个代码实现层,所有这些类都将作为 friend 添加到 Accessor。

并且为了进一步隐藏访问器只会被前向声明为 template <typename T> class Accessor; 的东西在公共(public)代码中。并在私有(private)代码中定义。

最佳答案

如果可以将与 m_impl 本身一起工作的所有逻辑移动到基类,则可以使派生类无法访问 m_impl,但允许它获得对 Impl 的引用,然后使 Access 类成为派生类的友元:

class Base {
  protected:
    class Impl;
    Impl& impl();
  private:
    std::unique_ptr<Impl> m_impl;
};

class Base::Impl {
  public: 
    Impl() {}
};

Base::Impl& Base::impl() { return *m_impl; }

class Derived : private Base {
  public:
    friend class Access;
    Derived() { 
      auto& ptr = impl(); // ok
      auto& ptr1 = m_impl; // error
    }
 };

class Access {
  public:
  Access(Derived& d) {
    auto& ptr = d.impl(); // ok
    auto& ptr1 = d.m_impl; // error
  }
};

关于c++ - 如何仅将实现公开给 pimpl 习语中的一组指定类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22611210/

相关文章:

c++ - 结构引用 (.) 运算符适用于 vc9 中的类名

c++ - Opengl sws_scale 不工作(段错误)

c++ - 实现涉及 Windows HANDLE 对象的复制构造函数

c++ - GEOS OverlayOp 相交操作

c++ - SDL2_gfx 屏幕在第二次循环后填充

c++ - CCSprite 在 COCOS2dx 中不作为物理体?

c++ - Qt OpenGL - 纹理透明度问题

c++ - 具有右值引用成员的通用复制构造函数

c++ - cmake os x 失败 ar 没有特定的存档成员

c++ - 如何在 Windows 7 64 位上安装 OpenSSL