const-correctness al pasar tipos complejos

Entonces, tengo cuatro clases:

App - esto representa el punto de entrada para la aplicación

Pagina principal - esto representa la pantalla de inicio

autenticador - esto representa una clase auxiliar/de utilidad para la autenticación

Página de inicio de sesión - esto representa una pantalla de inicio de sesión.

La aplicación, la página principal y la página de inicio de sesión tienen punteros a un autenticador y, de hecho, se pasa de la aplicación a la página principal y a la página de inicio de sesión cuando el usuario inicia la aplicación, llega a la pantalla principal y se le solicita que inicie sesión. crea MainPage, y si MainPage necesita iniciar sesión, crea LoginPage. El puntero del autenticador se pasa en la creación.

Digamos que el Autenticador se parece a esto:

class Authenticator {
public:
   std::string GetToken() const;
   void Login(std::string username, std::string pass);
}

Ahora, la aplicación creará un puntero normal, no constante para el autenticador, pero como no quiero que MainPage pueda modificar el autenticador, quiero que almacene un puntero constante (es decir, para que solo pueda llamar a funciones de miembros constantes en eso). Sin embargo, me gustaría que LoginPage pueda llamar a funciones de miembros no constantes, como Login(), por lo que cuando pase mi Autenticador de MainPage a LoginPage, tendré que desechar la constancia.

Mi pregunta es: ¿es malo hacerlo en esta situación? ¿Debería una clase que no puede modificar un objeto poder pasárselo a otra que sí pueda? ¿O sería mejor que la aplicación creara la página principal y la página de inicio de sesión al mismo tiempo y les diera a ambas el mismo autenticador para empezar? Mi único problema con esa opción es que creo una página de inicio de sesión de forma activa, en lugar de perezosamente, y prefiero hacerlo de forma perezosa.

Gracias de antemano.

preguntado el 16 de abril de 13 a las 08:04

Bueno, parece que puede estar proponiendo diseñar con un comportamiento indefinido, así que sí, hay una mejor manera. Seguro puede descartar const, pero si el objeto en sí es realmente constante, entonces modificarlo es UB. Si la cosa necesita ser modificada, entonces no es/no debe ser constante, punto. Suena como un defecto de diseño. ¿Dónde se crea esto? Pueden MainPage almacenar una versión const y LoginPage almacenar una versión no constante del mismo objeto no constante? ¿Pueden recuperarlo de otra fuente? -

@EdS. No es UB en este caso. El OP menciona el Authenticator se crea como non-const. -

@Angew: Lo siento OP, fallo de comprensión de lectura. -

4 Respuestas

Desde el punto de vista de las aplicaciones, MainPage is modificando el Autenticador. No importa si lo hace directamente o llama a otra parte (LoginPage) para que lo haga en su nombre. Entonces MainPage debería obtener un puntero no constante y luego debería pasarlo a su subpágina para iniciar sesión.

Si desea asegurarse de que su página principal no modifique el autenticador, debe podría implemente una clase base que almacene este puntero y tenga un método para llamar al cuadro de diálogo de inicio de sesión. El Autenticador es privado, el método está protegido. Luego puede derivar su propio MainPageDerived que no tiene la posibilidad (legal, no pirateada) de modificar el Autenticador, pero puede llamar a LoginPage si es necesario.

Tenga en cuenta que dije podría porque para 3 clases creo que eso es una ingeniería excesiva. Sin embargo, si tiene más páginas en el futuro, ese puede ser un enfoque válido.

Respondido 16 Abr '13, 08:04

Gracias por la sugerencia, bien podría hacerlo. - chicosherman

Te estás perdiendo una parte importante del concepto de constancia lógica. Cuando una clase acepta un puntero (o referencia) a un objeto const, promete NUNCA usar el puntero/referencia de una manera que pueda modificar el objeto. Por supuesto, esto significa pasarlo a otra persona que podría modificarlo.

En otras palabras, si MainPage está planeando pedirle a alguien que modifique el Authenticator para él (es decir, pasarle un puntero no constante a otra persona), también es responsable de las modificaciones y, por lo tanto, debería almacenarle un puntero no constante.

Respondido 16 Abr '13, 08:04

Desde el punto de vista de la interfaz: si tiene MainPage( Authenticator const* ), me estas prometiendo que nada MainPage modificará el estado observable de Authenticator. Directa o indirectamente, si MainPage luego pasa su puntero a otra clase que modificará el objeto, ha violado el contrato. Por lo tanto, en su caso, la corrección constante requiere MainPage( Authenticator* ): la construcción del código MainPage no le importa si las modificaciones son directas o indirectas; solo quiere saber cuál es el contrato y que se respete.

Respondido 16 Abr '13, 08:04

Dar MainPage solo lo que necesita. Puedes ver esto de varias maneras. Podría necesitar:

  • An AuthenticationTokenSource que proporciona una actualización Token.
  • An AuthenticatedExectuor que realiza Actions que MainPage define, pero AuthenticatedExectuor proporciona la autenticación ya que llama al Action

Probablemente hay otras formas, pero esas son las primeras que me vienen a la mente.

Respondido 16 Abr '13, 08:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.