4

保護されたメソッドZig::punt()を持つクラスがあり、クラス「Avocado」にのみアクセスできるようにしたい。C ++では、通常、「friend Avocado」指定子を使用してこれを行いますが、これにより、他のすべての変数が「Avocado」クラスにアクセスできるようになります。これはカプセル化を壊すので、私はこれを望んでいません。

私が望んでいることは不可能ですか、それとも私が望んでいることを達成するために使用できるあいまいなトリックがすでにそこにありますか?または、同じことを実現する代替のクラスデザインパターンでしょうか?

アイデアをよろしくお願いします!

4

3 に答える 3

4

これは醜いが機能するトリックです:

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

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

基本的に、アボカドにしたいインターフェースの部分だけを公開するミックスインクラスを追加します。アボカドと親しみのあるクラスを継承することで、最初に公開されたもの以外は何も公開されないという事実を利用しています。

于 2010-05-25T07:29:46.783 に答える
2

私は個人的にその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();(適用される場合とされない場合があります)

そしてもちろん、コンパイラはこの参照の受け渡しを最適化する可能性が非常に高いです。これは目的を果たさないため、設計が破損したり、不要な一時的なものが追加されたりすることはありません:)

于 2010-05-25T09:18:31.303 に答える
0

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);
}
于 2010-05-25T07:29:20.417 に答える