2010-09-16 25 views
12

En una aplicación C++, digamos que tengo una clase de ventana, que tiene varias instancias de una clase de control. Si la ventana de mi quería notificar a un control que se había hecho clic, puede ser que utilice:¿Es una mala práctica para un objeto secundario tener un puntero a su elemento primario?

control[n]->onClick(); 

Ahora vamos a decir que el control necesita saber el tamaño de la misma de ventana padre, o alguna otra información. Para esto, estaba considerando dar al control un puntero a sí mismo (esto) como parámetro para su constructor. Quisiera entonces hacer una llamada así desde el onClick método controles():

Size windowsize = parent->getSize(); 

¿Esto se considera una mala práctica, o de cualquier otra manera en contradicción con los valores de la programación orientada a objetos? Si es así, ¿cuál sería la forma "correcta" de hacer esto?

Como una pregunta complementaria, ¿sería mejor tener un vector de Clase o Clase *? ¿Vale la pena la complejidad añadida para la ganancia de velocidad? (Los cambios en el vector serían poco frecuentes).

+1

@Martin: ¿cuál es su problema ...? No tiene mucho sentido quejarse sin explicación ... –

+0

@Tony: Mark Cidade corrigió el título, que originalmente decía exactamente como la cita en el comentario de @Martin. Supongo que la queja es que fue un poco vago para un título. –

Respuesta

10

Puede considerar una jerarquía de controles como una estructura de datos de gráficos tipo árbol; cuando lo visualiza de esa manera, es bastante razonable que un control tenga un puntero a su padre.

En cuanto a si los objetos o punteros a los objetos deben almacenarse en un vector, bueno, depende. Por lo general, debería preferir almacenar objetos, pero muchas veces no puede hacerlo o no es práctico hacerlo. Por ejemplo, si necesita aprovechar el polimorfismo y almacenar diferentes tipos de cosas, todas derivadas de una clase base común, necesitará usar punteros.

Si almacena punteros, asegúrese de utilizar un puntero inteligente de algún tipo o un contenedor de puntero; de lo contrario, la seguridad de excepciones es una paliza.

5

De hecho, el patrón de diseño compuesto GOF se basa en las referencias padre explícitas.

Referencias padre explícitas. El mantenimiento de las referencias de los componentes secundarios a su matriz puede simplificar el recorrido y la administración de una estructura compuesta. La referencia principal simplifica el movimiento hacia arriba de la estructura y la eliminación de un componente. Las referencias principales también ayudan a admitir el patrón Cadena de responsabilidad (223) . El lugar habitual para definir la referencia primaria está en la clase Componente . Las clases Leaf y Composite pueden heredar la referencia y las operaciones que lo administran.

Con referencias de los padres, es esencial para mantener el invariante que todos hijos de un compuesto tienen como matriz del material compuesto que a su vez tiene como niños. La forma más fácil de es asegurar que se cambie el componente principal solo cuando se agrega o eliminado de un compuesto.Si esto puede implementarse una vez en Agregar y Eliminar operaciones de la clase Composite , entonces todas las pueden heredar las subclases, y la invariante se mantendrá automáticamente .

Por lo tanto, supongo que hay un lugar claro para tal diseño, dependiendo de los requisitos reales y el contexto.

4

No, está completamente bien. El único problema es que aumenta el nivel de acoplamiento entre instancias. Además, si considera el uso de punteros inteligentes como se indicó anteriormente, asegúrese de hacer que la referencia al padre sea "débil". Asumiendo que los árboles de su ventana no son demasiado profundos, podría considerar determinar el padre de manera dinámica, comenzando desde una ventana superior conocida.

2

Está bien. Sin embargo, asegúrese de que lo necesita porque puede complicar su código en situaciones donde un padre de un niño puede cambiar. Examine por qué el niño necesita saber quién es su padre y considere los costos y las alternativas. Una alternativa de ejemplo para su escenario sería: El cambio de tamaño puede venir de arriba hacia abajo cuando se cambia el tamaño de la ventana de un padre; puede decirle a sus hijos que cambien el tamaño repitiendo e invocando un método o estableciendo una propiedad. Cuando un niño necesita cambiar el tamaño (como un cuadro de texto que puede crecer según los datos que contiene) puede provocar un evento a cualquiera que lo escuche y le dice que cambió de tamaño y que el padre puede escuchar ese evento.

1

Si necesita hacerlo, considere pasar al padre como const*.

0

No está mal. Por ejemplo, en los widgets Qt cada widget tendrá su puntero como principal, incluso sin usar const*.

BTW: Es algo confuso ya que usted dijo que las personas "padre" pueden ser mal entendidas por el padre jerárquico.

Cuestiones relacionadas