PDA

Ver la Versión Completa : Stack OverFlow al pasar parametro en el constructor de un Form


Mialom
06-02-2008, 12:26:21
Buenos dias, y muchas gracias de antemano

estoy teniendo un problema cuando le paso un parámetro adicional a un form en el constructor, porque necesito dicho parametro para la funcionalidad propia que le voy a dar al form nuevo. Pero al crearlo, se embucla y al final me da un mensaje de desbordamiento de pila (Stack Overflow).

Muchas gracias.

maeyanes
06-02-2008, 15:37:23
Hola...

Bienvenido al Club, te recomiendo le des un vistazo a la Guía de Estilo (http://www.clubdelphi.com/foros/guiaestilo.php) de los foros...

Sobre tu problema... cual es el parámetro adicional que pasas?

Podemos ver el fragmento de código que te produce el Stack Overflow?



Saludos...

Mialom
06-02-2008, 16:23:10
Buenas tardes de nuevo,

El código es muy sencillo:
//-------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner, int x) // <-- Aqui pasa al constructor de la clase base
:TForm(Owner) // <-- Aqui entra y vuelve a mi constructor
{
...
}
//-------------------------------------------------------

Pasa de un constructor a otro hasta que se desborda la pila.

Su definición en el cabecero es:

__fastcall TForm1(TComponent* Owner, int x);

Y la llamada desde el otro fomulario es:

TForm *Form1 = new TForm(this, entero);
Form1->ShowModal();
delete Form1;

Muchas gracias, espero que esto explique mejor mi problema.
Un saludo.

jachguate
06-02-2008, 16:32:53
Creo que una forma sencilla de romper un bucle infinito es poner un punto de ruptura dentro de alguno de los métodos que se ejecutan como parte del bucle, examinar y recorrer la pila de llamadas durante 2 o 3 iteraciones.

Las causas típicas por las que ocurre este tipo de problema son:

Error en la condición que rompe con la recursividad, en una función o serie de funciones realmente recursivas.
Que se está llamando a un método por error, por ejemplo porque se pretende llamar a un método con el mismo nombre de otro objeto o porque se pretende llamar a un método con el mismo nombre de una clase ancestro.
Recursividad indirecta provocada por desconocimiento de la VCL, por ejemplo porque la modificación de alguna propiedad de un objeto dispara un evento cuyo manejador termina llamando nuevamente al método que modifica el valor. Caso típico de modificar un valor de un campo dentro de su propio evento OnChange:

procedure TForm1.Tabla1Campo1Change(Parametros);
begin
Tabla1Campo1.AsInteger := Tabla1Campo1.AsInteger + 1;
end;


Para evitar esto último, en ocasiones donde no veo otra solución, suelo valerme de una bandera que evite la llamada recursiva:


procedure TForm1.Tabla1Campo1Change(Parametros);
begin
if not YaModificandoCampo1 then
begin
YaModificandoCampo1 := True;
try
Tabla1Campo1.AsInteger := Tabla1Campo1.AsInteger + 1;
finally
YaModificandoCampo1 := False;
end;
end;
end;



Hasta luego.

;)

maeyanes
06-02-2008, 16:43:15
Hola...

No se bien como se llama un método heredado en C++ Builder, pero creo que ahí está tu problema...

En Delphi se haría así:


constructor Create(AOwner: TComponent; X: Integer);
begin
inherited Create(AOwner); // Si te fijas, usamos la palabra reservada inherited
// Demás código de construcción...
end;



Saludos...

Mialom
07-02-2008, 09:21:11
Buenos dias,

ya he encontrado una solución para pasar los parámetros al constructor del formulario, la cuestion es que el constructor se embucla hasta que se desborda la pila (Stack Overflow) debido a que el parámetro que le paso es de tipo Entero, he probado a pasarle parámetros de otro tipo de datos como AnsiString, String, TDateTime y Float y funciona perfectamente. De momento le pasaré el parametro como cadena de texto y ya dentro del formulario nuevo le haré un cast a entero, pero no he conseguido averiguar el porque de que no admita parámetros de valor entero.

Muchas gracias por vuestra ayuda, y si averiguo el porque ya os lo contaré.
Un saludo

Antonioveneroso
15-02-2008, 20:51:59
Creo que en una ocasión hice algo así, pero en lugar de pasarle un int le pasaba un short... necesariamente debe ser int?

escafandra
15-02-2008, 23:29:26
Creo que la solución es mucho mas simple y que te permite pasar cualquier tipo de parámetro. Efectivamente pasa por conocer el funcionamiento de Builder con las VCL.

Existen dos tipos de formulario, los autocreados, por defecto, y los disponibles. Al definir un formulario, Builder lo asume como autocreado, de forma que no tenemos que llamar explícitamente al constructor para crearlo. Esto choca al programador en C++.

En opciones del proyecto, podemos pasar un formulario autocreado a disponible, que quiere decir "no esta creado, solo definido y por tanto disponible"

Este tipo, disponible, se comporta como cualquier objeto definido en C++. De hecho y según tu código, es así como tu quieres usarlo puesto que lo creas con un new y luego lo destruyes.

Te aseguro que si lo defines como disponible, podrás pasar un int en el constructor.

Saludos.

Lepe
16-02-2008, 11:56:03
Pregunta de diseño:

¿es realmente necesario ese parámetro para la construcción de la ventana?

- Si, sigue como vas.
- No, crea una propiedad y la asignas después de crear la ventana.

Ejemplo de un ProgressBar: podría pensarse que los límites (Max y Min) formase parte del constructor del componente, pero si te fijas, son propiedades.

Saludos

Mialom
17-02-2008, 23:23:22
Hola a todos,

el formulario no se crea automaticamente al ejecutar la aplicacion, ya que solo dejo como formularios autocreados el main form.
Respecto a si con un short da error la verdad es que no lo he probado pero es una buena idea aunque creo que pudiera dar el mismo resultado.

De todas formas muchas gracias por las ideas, siempre entre todos sacaremos algo mas en claro que una sola mente.

Un saludo

escafandra
18-02-2008, 01:06:47
Hola a todos,

el formulario no se crea automaticamente al ejecutar la aplicacion, ya que solo dejo como formularios autocreados el main form.
Respecto a si con un short da error la verdad es que no lo he probado pero es una buena idea aunque creo que pudiera dar el mismo resultado.

De todas formas muchas gracias por las ideas, siempre entre todos sacaremos algo mas en claro que una sola mente.

Un saludo

Pues... Yo soy muy aficionado a pasar parámetros en los constructores. Nunca he tenido ese problema. Al ver tu caso hice el experimento, como comentabas. Y pensando en el problema de los autocreados, deje el form que iba a recibir el parámetro añadido (int) como autocreado. Entonces apareció el error que tu mencionas. Lo cambié a disponible y desapareció el error.

De todas formas tu hablas de un Form1 (TForm1(TComponent* Owner, int x)), este por defecto, y según los denomina Builder, es el mainForm. Te comento esto porque ese siempre es autocreado. En este caso no tiene sentido el paso de parámetros en el constructor. Yo siempre les doy otros nombres mas personales...

Repito, a mi con los formularios disponibles, no me pasa el error "Stack Overflow".

Repasa toda la configuración de tu proyecto....

Saludos.

Lepe
18-02-2008, 12:02:36
Al añadir un parámetro, te estas cargando toda la herencia. Además de hacer incompatible tu ventana con toda la VCL (de ahí el problema de autocreate Forms).

La ventana ya se podía crear sin tu parámetro "x", eso quiere decir, que no es realmente necesario modificar el constructor.

Se debe crear una propiedad, todo lo demás son chapuzas, por mucho C++ que se use.

Saludos

escafandra
18-02-2008, 18:08:23
No creo que te cargues la herencia al colocar un parámetro en un constructor de una clase VCL.

El hecho de que ese parámetro sea una propiedad, no cambia nada, de hecho cualquier elemento de la clase que, no sea una función,
es una propiedad. En ocasiones ese parámetro, no tiene porqué almacenarse en ninguna variable de la clase, y por lo tanto deja de ser una propiedad.

Estoy de acuerdo que posiblemente ese parámetro pueda pasarse fuera del constructor, pero eso no quiere decir que no pueda hacerlo como ha decidido. de hecho al hacerlo así se simplifica la sintaxis.

Yo suelo programar un formulario que denomino TConfig al que le paso un parámetro en el constructor que es otra clase o estructura con los datos de la configuración de mi programa. Esta forma de abordar el problema me facilita mucho la tarea. Por otro lado es la forma de programar en C++, y aunque las VCL se salen un poco de la ortodoxia, no son incompatibles.

Son formas diferentes de ver las cosas.

Saludos.