2010-06-10 22 views
6

estaba navegando código de mi maestro cuando me encontré con este:Inicializar Puntero A través de la función

Order* order1 = NULL;

continuación

order1 = order(customer1, product2);

que llama a

Order* order(Customer* customer, Product* product) 
{ 
    return new Order(customer, product); 
} 

Esto parece código tonto. No estoy seguro de por qué, pero la maestra inicializó todos los apuntadores a NULL en lugar de declararlos de inmediato (mirando el código es completamente posible, pero eligió no hacerlo).

Mi pregunta es: ¿es este código bueno o aceptable? ¿La llamada a la función tiene algún beneficio sobre llamar a un constructor explícitamente? ¿Y cómo funciona el nuevo en este caso? Puedo imaginar el código de ahora como algo así como:

order1 = new Order(customer, product);

+1

Solicitar * = order1 nueva Orden (clientes, productos); es exactamente igual que el código anterior, solo que esto es más legible;) – RvdK

+0

¿Qué experiencia y/o calificaciones tiene su maestro que sugieren que debe prestar la menor atención a lo que él le dice? Cuando te confronten con un maestro, esta debería ser tu primera pregunta para ellos. Hablando como un ex maestro aquí. –

Respuesta

8

Init a NULL

[editar] ya que no hay una discusión válida, he cambiado el orden de las opciones un poco para resaltar la opción recomendada.

Las variables deben ser declaradas como local y lo más tarde posible y inicializan inmediatamente. Por lo tanto, el patrón más común es:

Order * order1 = order(...); 

justo antes de que se requiere order1.
Si hay alguna razón para separar la declaración de order1 de la ejemplificación, así:

Order * order1; // Oh no! not initialized! 
// ... some code 
order1 = order(...); 

order1 debe ser inicializado a NULL, para evitar los errores comunes que se producen con las variables sin inicializar, introduce fácilmente cuando // some code changes.

método de fábrica
Una vez más, hay algo más cambio resilencia aquí: los requisitos para crear instancias de un Order puede cambiar. Hay dos escenarios en los que puedo pensar:

(1) La validación no puede ser hecha por el constructor de la Orden. Order puede provenir de una biblioteca tercera parte y no se puede cambiar, o de instancias tiene que añadir la validación de que no está dentro del alcance de Order:

Order* order(Customer* customer, Product* product)    
{  
    // Order can't validate these, since it doesn't "know" the database  
    database.ValidateCustomer(customer); // throws on error 
    database.ValidateProduct(product); // throws on error 

    return new Order(customer, product);    
} 

(2) Es posible que tenga una orden que se comporta de manera diferente.

class DemoOrder : public Order { ... } 

Order* order(Customer* customer, Product* product)    
{    
    if (demoMode) 
     return new DemoOrder(customer, product); // doesn't write to web service 
    else 
     return new Order(customer, product);    
} 

Sin embargo, yo no haría de esto un patrón general a ciegas.

+6

-1 ¡NO! No _in_ inicialice 'order' en NULL antes de' //...some code'.O bien ese código necesita un pedido, en cuyo caso debe crear uno o (lo más probable) no. En ese caso, no _not_ declare 'order' tan temprano. Mueva la declaración a donde realmente necesita una 'orden'. En ese punto, ya no es necesario inicializar el puntero a NULL; solo crea un objeto Order. – MSalters

+0

Tiene razón: la definición de orden debe retrasarse hasta que sea necesario. Supuse que hay alguna razón (tal vez oscura) para separarlos. He actualizado mi respuesta a inclduethat. – peterchen

+0

@MSalters, estuvo de acuerdo como aparece en este caso, pero ¿qué ocurre si 'orden' es una variable miembro, que el constructor no pudo inicializar a un valor correcto? En este caso, tiendo a ir con la respuesta original de Peter Chen. –

2

Si eso es realmente todo el código importante, no veo ningún beneficio para la función o el valor inicial nulo. new funciona de la manera en que siempre funciona. Construye una orden y le devuelve un puntero, que a su vez es devuelto por order.

0

Para el código dado, no hay diferencia. Es mejor inicializar el objeto de orden con un objeto recién creado en un solo lugar. Evitará utilizar la variable de orden inicializada con el valor NULL

2

El código proporcionado podría ser importante si la asignación a NULL ocurre en una función, p. el constructor, y la asignación que llama al new ocurre en otra función. Aquí hay tres razones;

  • Si el cliente y los parámetros del producto pueden no estar disponibles cuando se llamó al order = NULL.
  • El valor NULL podría ser significativo mientras tanto para que otras funciones sepan que el pedido aún no se ha creado.
  • Si la clase de pedido tomó muchos recursos, posponer su inicialización podría ser beneficioso.

Mejor que le pregunte a su profesor por qué lo hicieron de esta manera. A veces las conclusiones obvias no son las correctas.

+0

Acepto, excepto que la variable de orden pudo haber sido definida en la declaración. Todos los parámetros ya fueron dados. Esta es la Programación 1, por lo que el ejemplo también es bastante breve y trivial. Es por eso que me estaba confundiendo tanto. – IAE

3

Me parece que su profesor es un viejo programador de C que no ha perdido por completo sus viejos hábitos. En los viejos tiempos, tenía que declarar todas las variables al comienzo de una función, por lo que no es inusual ver que algunos temporizadores antiguos siguen haciéndolo.

1

Si las cosas realmente son como las describes, entonces el código de tu maestro ilustra algunas prácticas de programación bastante malas.

Su pregunta se ha etiquetado C++. En C++, la técnica adecuada sería mover la declaración de la variable al punto donde pueda inicializarse significativamente. Es decir. que debería haber buscado la manera siguiente

Order* order1 = order(customer1, product2); 

Lo mismo appliy al código C99, C99 ya que permite declarar variables en el medio de la cuadra.

En el código C, la declaración debe colocarse al principio del bloque, lo que puede provocar situaciones en las que no se pueda inicializar de forma significativa una variable en el punto de declaración. Algunas personas creen que en este caso debe inicializar la variable con algo, cualquier cosa para mantenerla inicializada en lugar de dejarla sin inicializar. Puedo respetar esto como una cuestión de preferencia personal, comprar personalmente lo considero contraproducente. Interfiere con las optimizaciones del compilador y tiende a ocultar errores al pasarlos por debajo de la alfombra (en lugar de fomentar correcciones adecuadas).

diría que el código C++ de su maestro sufre de algunos malos hábitos traídos de C.

Cuestiones relacionadas