C++: Is there a way to limit access to certain methods to certain classes without exposing other private members?

半世苍凉 提交于 2020-02-01 06:55:27

问题


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!


回答1:


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.




回答2:


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 :)




回答3:


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);
}


来源:https://stackoverflow.com/questions/2902717/c-is-there-a-way-to-limit-access-to-certain-methods-to-certain-classes-withou

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!