¿Por qué C++ tiene public
miembros que cualquier persona puede llamar y friend
declaraciones que exponen todosprivate
miembros a dados clases o métodos extranjeros, pero no ofrecen ninguna sintaxis para exponer a los miembros particulares a los que llaman dados?limpio C++ amigo granular equivalente? (Respuesta: Abogado-Cliente Idiom)
Quiero expresar las interfaces con algunas rutinas para que las invoquen solo las personas que llaman sin tener que darles acceso completo a todas las partes privadas, lo cual es razonable. Lo mejor que pude encontrar (más abajo) y las sugerencias de otros hasta ahora giran en torno a modismos/patrones de variabilidad indirecta, donde realmente solo quiero una forma de tener solo, definiciones de clase simples que indican explícitamente lo que llaman (más granularly que me, mis hijos, o cualquiera)) puede acceder a qué miembros. ¿Cuál es la mejor manera de expresar el concepto a continuación?
// 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); }
};
Estoy muy lejos de ser un gurú de la organización de software, pero se siente como la sencillez de interfaz y el principio del mínimo privilegio entran en conflicto directo en este aspecto de la lengua. Un ejemplo más claro de mi deseo podría ser una clase Person
con métodos declarados como takePill(Medicine *)
tellTheTruth()
y forfeitDollars(unsigned int)
que sólo Physician
, Judge
, o TaxMan
casos/métodos miembros, respectivamente, deberían incluso considerar la invocación. Necesito una sola proxy o clases de interfaz para cada aspecto importante de la interfaz, pero dígame si sabe que me estoy perdiendo algo.
respuesta aceptada de Drew Hall: Dr Dobbs - Friendship and the Attorney-Client Idiom
El código anterior originalmente llamado la clase contenedora 'proxy' en lugar de 'abogado' y se utiliza punteros en lugar de referencias, pero por lo demás fue equivalente a lo que dibujó encontró, que luego considerada la mejor solución conocida en general. (No darme palmaditas en la espalda demasiado fuerte ...) También cambié la firma de 'restringido' para demostrar el reenvío de parámetros. El costo total de esta expresión idiomática es una declaración de clase y una de amigo por conjunto de permisos, una declaración de amigo por llamada autorizada establecida y una versión de envío por método expuesto por conjunto de permisos. La mayor parte de la mejor discusión a continuación gira en torno a la repetición de la llamada de reenvío que una expresión idiomática 'clave' muy similar evita a costa de una protección menos directa.
Creo que esta es una pregunta interesante sobre el diseño del lenguaje: ¿cómo manejaría esto su lenguaje ideal? Pero esto parece demasiado ingenioso para la pequeña cantidad de veces que se requieren amigos. Para un control de acceso más granular que público/protegido/privado, por lo general un prefijo de nombre de función o comentario es suficiente. Prefiero el enfoque de Python, que es "los usuarios deberían hacer lo correcto" en lugar del inútil intento de aplicarlo. – Stephen
@Stephen: El enfoque habitual de C++ es detectar tantos errores posibles en tiempo de compilación como sea posible. Creo que el enfoque de Matthieus está cerca de lo que me gustaría de la compatibilidad con el lenguaje: Permitir el acceso por clase o función en función de los grupos. –
@Georg: Creo que el enfoque de C++ es permitir el acceso en la medida en que el lenguaje lo permita. Ese nivel de control de acceso sería bueno, pero no creo que la creación de objetos de clave falsos sea algo que diseñaría en un lenguaje :) Claro, la mayoría logra el objetivo (ignorando el hecho de que las claves se pueden pasar), pero - en mi opinión, es más trabajo del que debería dedicarse al tema :) Estoy bien acordar desacuerdo sobre esto con todos ustedes, y tal vez cambiaría de opinión si trabajaba en su base de código. – Stephen