Почему у C++ есть public
члены, которые любой может вызвать и добавить в friend
объявления, которые предоставляют всем private
членам данные иностранные классы или методы, но не предлагают синтаксиса для предоставления определенных членов указанным вызывающим лицам?
Я хочу выразить интерфейсы с некоторыми подпрограммами, которые будут вызывать только известные вызывающие абоненты, не предоставляя этим вызывающим пользователям полный доступ ко всем частным лицам, что кажется разумным. Лучшее, что я мог придумать сам (см. Ниже) и предложения других, пока что вращаются вокруг идиом/паттерна различной косвенности, где я действительно просто хочу иметь один простой набор определений классов, которые явно указывают, какие вызывающие абоненты (более детально, чем я), мои дети, или абсолютно любой) могут получить доступ к каким членам. Как лучше всего выразить концепцию ниже?
// Can I grant Y::usesX(...) selective X::restricted(...) access more cleanly?
void Y::usesX(int n, X *x, int m) {
X::AttorneyY::restricted(*x, n);
}
struct X {
class AttorneyY; // Proxies restricted state to part or all of Y.
private:
void restricted(int); // Something preferably selectively available.
friend class AttorneyY; // Give trusted member class private access.
int personal_; // Truly private state ...
};
// Single abstract permission. Can add more friends or forwards.
class X::AttorneyY {
friend void Y::usesX(int, X *, int);
inline static void restricted(X &x, int n) { x.restricted(n); }
};
Я далеко не гуру организации программного обеспечения, но мне кажется, что простота интерфейса и принцип наименьших привилегий прямо расходятся в этом аспекте языка. Более ясным примером для моего желания может быть класс Person
с объявленными методами, такими как takePill(Medicine *)
tellTheTruth()
и forfeitDollars(unsigned int)
что только TaxMan
экземпляров/членов Physician
, Judge
или TaxMan
, соответственно, должны даже учитывать вызов. Потребность в одноразовых прокси или классах интерфейса для каждого важного аспекта интерфейса меня не устраивает, но, пожалуйста, говорите, если знаете, что я что-то упустил.
Ответ принят от Дрю Холла: Доктор Доббс - дружба и идиома адвокат-клиент
Приведенный выше код изначально называл класс-оболочку "Proxy" вместо "Attorney" и использовал указатели вместо ссылок, но в остальном он был эквивалентен тому, что нашел Дрю, который я тогда считал лучшим общеизвестным решением. (Не слишком сильно поглаживать себя по спине...) Я также изменил сигнатуру "limited", чтобы продемонстрировать пересылку параметров. Общая стоимость этой идиомы составляет один класс и одно объявление друга на каждый набор разрешений, одно объявление друга на один утвержденный вызывающий набор и одну оболочку переадресации для каждого открытого метода на каждый набор разрешений. Большая часть лучшего обсуждения ниже вращается вокруг шаблона переадресации вызовов, которого избегает очень похожая идиома "Ключ" за счет меньшей прямой защиты.