Ограничить доступ метода к определенному классу в C ++ - PullRequest
2 голосов
/ 04 декабря 2009

У меня есть два тесно связанных класса, которые я назову Widget и Sprocket. В Sprocket есть набор методов, которые я хочу вызывать из Widget, но не из любого другого класса. Я также не хочу объявлять Widget другом Spocket, потому что это даст Widget доступ ко ВСЕМ защищенным и закрытым членам. Я хочу ограничить доступ Widget только к определенному набору методов.

Одно из решений, которое я придумал, - создать внутри Sprocket вложенный класс, содержащий обертки для этих методов, и сделать Widget другом этого вложенного класса. Например:

class Sprocket
{
public:
    class WidgetInterface
    {
        friend class Widget;
        WidgetInterface(Sprocket* parent) : mParent(parent) {}

    private:
        void A() { mParent->A(); }
        void B() { mParent->B(); }

        Sprocket* mParent;
    };

private:
    void A() { ... }
    void B() { ... }
};

class Widget
{
public:
    Widget(Sprocket* sprock) : mSprocketIface(sprock) {}

    void doStuff() { mSprocketIface.A(); }  // Widget can call Sprocket::A()

private:
    Sprocket::WidgetInterface mSprocketIface;
};

Это приводит к некоторому дублированию кода, поскольку сигнатуры методов теперь объявляются в двух местах, но это работает. Но теперь предположим, что я хочу добавить подкласс Widget с именем SpecialWidget и хочу, чтобы этот класс также имел доступ к методам Sprocket. Я могу просто добавить этот новый класс в список друзей Sprocket или добавить еще один набор защищенных оболочек в Widget, к которым SpecialWidget (и любой другой подкласс) могут получить доступ, но вы можете видеть, что это становится проблемой обслуживания. Я не хочу обновлять список друзей или оболочки, если я добавляю новые классы или изменяю сигнатуру метода. Если я использую подход «добавить еще один набор оболочек», сигнатуры метода будут продублированы в трех местах!

Кто-нибудь знает более простой и понятный способ сделать это?

Ответы [ 4 ]

2 голосов
/ 04 декабря 2009

Если у вас есть два тесно связанных класса, то на самом деле не стоит пытаться сделать friend доступ более детальным, чем он есть. Вы контролируете реализацию обоих, и вам следует доверять себе достаточно, чтобы не злоупотреблять способностью вызывать некоторые методы, которые вам, строго говоря, не нужны.

Если вы хотите прояснить это для будущих разработчиков кода, добавьте комментарий к объявлению friend, объясняющий, почему он существует (хорошая идея в целом), и какие частные методы разрешено вызывать классом Friend. .

1 голос
/ 04 декабря 2009

Я бы реализовал WidgetInterface как реальный интерфейс, унаследованный Sprocket, поэтому A и B - это все, что Widget знает. Хорошо, другие тоже могут использовать этот интерфейс, но у них, вероятно, будет причина для этого.

1 голос
/ 04 декабря 2009

Sprocket имеет набор методов, которые я хочу вызывать из Widget, но не из любого другого класса.

Почему бы не избавить себя от неприятностей и не реализовать этот набор методов в Widget, возможно, добавив параметр Sprocket к этим методам?

0 голосов
/ 04 декабря 2009

Секрет в том, что все это управление доступом бессмысленно и иллюзорно, и нет никакого способа ограничить доступ к чему-либо. Вы просто усложняете вещи и затрудняете выяснить, какие части виджета в порядке, а какие нет. Вместо этого, сделайте интерфейс для виджета и звездочки более очевидным, и, возможно, у виджета есть собственная звездочка. Если люди настолько невежественны, что нарушат это, это не поможет, но если вы сделаете что-то отвратительное и сложное для понимания, это гарантирует, что даже люди, хорошо знающие С ++, не смогут легко его использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...