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)
这样的方法,只有Physician
、Judge
或TaxMan
实例/成员方法才应该考虑调用。需要针对每个主要接口方面创建一次性代理或接口类让我感到不适,但如果您知道我漏了什么,请说出来。
答案来自Drew Hall:Dr Dobbs-Friendship and the Attorney-Client Idiom
上面的代码最初将包装器类称为“Proxy”,而不是“Attorney”,并使用指针而不是引用,但除此之外与Drew发现的相当。然后我认为这是最好的普遍已知解决方案。(不要过分恭维自己……)我还更改了“restricted”的签名以演示参数转发。这种惯用法的总成本是每个权限集合一个类和一个友元声明,每个已批准调用者一个友元声明,每个暴露方法每个权限集合一个转发包装器。大部分更好的讨论都围绕着非常相似的“Key”惯用法避免了转发调用样板代码,但以更少直接的保护为代价。
AccessGroup foo { class A; void f(); };
和void g() restrictedTo(foo);
这样的方式。哦,好吧,人总是要做梦的... :) - Georg Fritzschevoid g() restrictedTo<int B::f(), class C>;
。我还没有真正考虑过语法,但完整的实体可能并不总是必要的。 - Jeff