C++:有没有办法限制对某些类的某些方法的访问而不暴露其他私有成员?

发布于 2024-09-02 09:55:03 字数 226 浏览 8 评论 0原文

我有一个带有受保护方法 Zig::punt() 的类,我只希望“Avocado”类可以访问它。在 C++ 中,您通常会使用“friend Avocado”说明符来执行此操作,但这将导致“Avocado”类可以访问所有其他变量;我不想要这个,因为这会破坏封装。

我想要的东西是不可能的吗,还是已经存在一个我可以用来实现我想要的东西的晦涩技巧?或者可能可以实现相同目标的替代类设计模式?

预先感谢您的任何想法!

I have a class with a protected method Zig::punt() and I only want it to be accessible to the class "Avocado". In C++, you'll normally do this using the "friend Avocado" specifier, but this will cause all of the other variables to become accessible to "Avocado" class; I don't want this because this breaks encapsulation.

Is what I want impossible, or does there already exist an obscure trick out there that I can use to achieve what I want? Or possibly alternative class design patterns that'll achieve the same thing?

Thanks in advance for any ideas!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清风不识月 2024-09-09 09:55:03

这是一个丑陋但有效的技巧:

class AvocadoFriender {
protected:
  virtual void punt() = 0;
  friend class Avocado; 
}

class Zig : public AvocadoFriender {
  ...
protected:
  void punt();
}

基本上,您添加一个 mixin 类,该类仅向 Avocado 公开您想要的接口部分。我们利用了这样一个事实:通过继承与 Avocado 友好的类,除了最初暴露的内容之外,您不会再暴露任何其他内容。

Here's an ugly yet working trick:

class AvocadoFriender {
protected:
  virtual void punt() = 0;
  friend class Avocado; 
}

class Zig : public AvocadoFriender {
  ...
protected:
  void punt();
}

Basically you add a mixin class that exposes only the part of the interface that you want to Avocado. We take advantage of the fact that by inheriting a class that is befriended to Avocado you don't expose anything more except what was exposed originally.

等待我真够勒 2024-09-09 09:55:03

我个人喜欢 Key 模式。

class WannaBeFriend { /**/ };

class WannaBeFriendKey: boost::noncopyable
{
  friend class WannaBeFriend;
  WannaBeFriendKey () {}
};

现在:

class LimitedAccess
{
public:
  Item& accessItem(const WannaBeFriendKey&) { return mItem; }

private:
  Item mItem;
  Item mOtherItem;
};

我真的很喜欢这个解决方案,因为:

  • 您只需要一个前向声明(例如友谊),
  • 您没有友谊授予的完全访问权限,而是只授予有限的访问权限,
  • 而且 在类编写器的完全控制下可以完全清楚什么可以访问以及可以从谁访问,从而简化调试
  • 可以将此访问权限授予 WannaBeFriend 的子类:它只需要公开一个 protected: static const WannaBeFriend& 。 Key();(可能适用,也可能不适用)

当然,编译器很可能会优化此引用的传递,因为它没有任何目的,因此它不会破坏设计,也不会添加不必要的内容临时工:)

I personally like the Key pattern.

class WannaBeFriend { /**/ };

class WannaBeFriendKey: boost::noncopyable
{
  friend class WannaBeFriend;
  WannaBeFriendKey () {}
};

And now:

class LimitedAccess
{
public:
  Item& accessItem(const WannaBeFriendKey&) { return mItem; }

private:
  Item mItem;
  Item mOtherItem;
};

I really like this solution because:

  • you only need a forward declaration (like for friendship)
  • you don't have the full access granted by friendship, instead only a limited access is granted, under the full control of the class writer
  • moreover it's perfectly clear what can be accessed and from whom, thus easing debugging
  • this access can be granted to child classes of WannaBeFriend: it only needs exposing a protected: static const WannaBeFriend& Key(); (may or may not apply)

And of course, it's very likely that the compiler will optimize the passing of this reference since it does not serve any purpose, so it does not corrupt the design nor add unnecessary temporaries :)

懷念過去 2024-09-09 09:55:03

您可以向 Zig 类添加代理

class Foo
{
    private:
        int m_x, m_y;
    public:
        class Bar
        {
            friend class Baz;
            int& x(Foo& blubb)
            {
                return blubb.m_x;
            }
        };
        friend class Bar;
};

class Baz
{
    public:
        void grml(Foo& f)
        {
            Foo::Bar b;
            // Yes, this looks awful
            b.x(f) = 42;
        }
};

void z()
{
    Foo f;
    Baz b;
    b.grml(f);
}

You can add a proxy to the Zig class

class Foo
{
    private:
        int m_x, m_y;
    public:
        class Bar
        {
            friend class Baz;
            int& x(Foo& blubb)
            {
                return blubb.m_x;
            }
        };
        friend class Bar;
};

class Baz
{
    public:
        void grml(Foo& f)
        {
            Foo::Bar b;
            // Yes, this looks awful
            b.x(f) = 42;
        }
};

void z()
{
    Foo f;
    Baz b;
    b.grml(f);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文