Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Borrar objetos creados dinámicamente (https://www.clubdelphi.com/foros/showthread.php?t=91837)

Angel.Matilla 11-05-2017 12:55:36

Borrar objetos creados dinámicamente
 
En el OnCreate de un formulario, dependiendo del valor de una variable, creo de forma dinámica un TListView o un TRadioGroup así:
Código PHP:

void __fastcall TfCalEst::FormCreate(TObject *Sender)
{
     if (
mOpcMenu->Tag == || mOpcMenu->Tag == 4)
     {
          
Panel->Width 300;

          
TListView *Lista = new TListView(Panel);
          [...]
     }
     else
     {
          
TRadioGroup *RadioGroup1 = new TRadioGroup(Panel);
          [...]
     }


Esto, evidentemente, se ejecuta sin mayor problema. En un evento OnClick de un botón pido al usuario un dato para hacer unos cálculos; por ejemplo:
Código PHP:

void __fastcall TfCalEst::Button1Click(TObject *Sender)
{
     try
     {
          switch (
mOpcMenu->Tag)
          {
               case 
'1':
               case 
'2':
                    if (!
InputQuery(Application->Title"Indique el número de años a considerar para la estadística."cAux))
                              throw 
Exception("");
                    if (
StrToIntDef(cAux0) < || StrToIntDef(cAux0) > 5)
                         throw 
Exception("El valor introducido (" cAux ") es incorrecto.");
                    break;
               case 
'3':
                    [...]
                    break;
               case 
'4':
                    [...]
                    break;
          }
     }
     catch(
Exception &Exc)
     {
          if (!
Exc.Message.IsEmpty())
               
Mensaje(1Exc.Message"Volver");
          
FormCreate(NULL);
          return;
     }


Dado que si se produce una excepción se vuelve al OnCreate me interesaría que en ese catch pudiera hacer un delete de los objetos que haya creado al lanzarse el módulo pero no se me ocurre como hacerlo.

mamcx 11-05-2017 17:25:23

El que tengas este problema evidencia que el flujo que tienes actualmente no es correcto. Cuando se empieza con ideas de como "hackear" algo es un "Code Smell".


Además, estas diciendo que tienes una dependencia circular? Deberias mejor ver cómo romperla. Casi siempre las dependencias circulares son un error de diseño (a menos que explícitamente estemos modelando un grafo).

Angel.Matilla 11-05-2017 18:32:57

Gracias por la respuesta, pero tu explicación no me aporta nada.

roman 11-05-2017 19:12:08

Hombre, un aporte no siempre viene en forma de código puntual. Lo que Mario te indica, y estoy de acuerdo con él, es que más allá de una posible solución exacta a tu problema, deberías considerar el hecho de que tu diseño es incorrecto. De entrada, un evento como FormCreate no está pensado para ser llamado explícitamente en tu código y además, cualquier cosa que pongas ahí, debería ser exclusivamente usada al crear el formulario y no en momentos posteriores.

Ahora, específicamente, si bien no manejo con soltura C++, me parece que los objetos Lista y RadioGroup1 son variables locales al método así que no tienes forma de acceder a ellos en otros contextos y por tanto no hay cómo borrarlos. Quizá deberías tener variables Lista y RadioGroup declaradas fuera del método, posiblemente como campos privados de la clase del formulario y usar esas variables para construir los objetos y, en su caso borrarlos desde la excepción.

Pero, reitero, sería aconsejable que revisaras el diseño de la aplicación.

LineComment Saludos

Angel.Matilla 11-05-2017 19:16:18

Acepto tu sugerencia porque me parece muy correcta y seguramente (lo evaluaré) tenga un error garrafal de concepto; es un manía que tengo bastante habitual el declarar elementos en el OnCreate y, cierto es, que no es lo más lógico.

Mi comentario anterior no es porque no me facilitara código; es simplemente porque poner un enlace a wikipedia o sugerir un hackeo es cualquier cosa menos ayuda.

mamcx 11-05-2017 21:35:19

Cita:

Empezado por Angel.Matilla (Mensaje 516578)
Mi comentario anterior no es porque no me facilitara código; es simplemente porque poner un enlace a wikipedia o sugerir un hackeo (*es realmente lo contrario!) es cualquier cosa menos ayuda.

El asunto es que el código tal como está es el problema. Y mientras más profundo sigas en esa línea mas difícil será. (Algo que aprendi luego de 4 meses de tratar de poner a andar un proyecto hecho por una multinacional, cuando debi aceptar que habia que reescribir toda la logica de GUI. Ahora, este si que era malo del todo!)

Además, no es claro cual es el flujo de la app, así que es difícil deducir que es lo que hay que hacer! Esa es la razón por la que

a) No es posible dar una respuesta concreta
b) El que tengas que hacer la pregunta, porque el "Code Smell" te esta insinuando que hay un problema, pero precisamente, te impide ver una solución.

---

La lógica GUI no es muy diferente a normal.

Debería ser maso:

Llamando -> ConstructorGUI(parámetros) -> GUI

Lo dificil es retornar valores o cuando desde "Llamando" hay que saber que paso con la GUI.

La manera mas simple es usando un callback, o armando un delegado.

Los eventos deberia ser "reacciones", no usarse en la logica normal (porque los eventos no tienen un orden predecible y terminan armando un flujo espaguetti). Un form es un objeto, asi que puedes agregar tus propios constructores de forma igual.

ecfisa 11-05-2017 22:15:22

Hola.

Cita:

Empezado por roman (Mensaje 516577)
...
Ahora, específicamente, si bien no manejo con soltura C++, me parece que los objetos Lista y RadioGroup1 son variables locales al método así que no tienes forma de acceder a ellos en otros contextos y por tanto no hay cómo borrarlos. Quizá deberías tener variables Lista y RadioGroup declaradas fuera del método, posiblemente como campos privados de la clase del formulario y usar esas variables para construir los objetos y, en su caso borrarlos desde la excepción.

Coincido plenamente.
Cita:

Empezado por mamcx (Mensaje 516582)
...
Los eventos deberia ser "reacciones", no usarse en la logica normal (porque los eventos no tienen un orden predecible y terminan armando un flujo espaguetti).

Totalmente de acuerdo.



A modo de ejemplo,

.hpp:
Código:

...
class TfCalEst : public TForm
{
__published:       
  ...
private:       
  TRadioGroup* FRadioGroup;
  TListView*  FListView;
  void __fastcall TfCalEst::CreateControl( const int op );
public:               
  ...
};

.cpp
Código:

void __fastcall TForm1::CreateControl( const int op )
{

  if (op == 3 || op == 4) {
    delete FListView;
    FListView = NULL;

    FListView = new TListView(Panel1);
    ...
  }
  else {
    delete FRadioGroup;
    FRadioGroup = NULL;

    FRadioGroup = new TRadioGroup(Panel1);
    ...
  }
}

void __fastcall TfCalEst::FormCreate(TObject *Sender)
{
  CreateControl ( mOpcMenu->Tag );
}

[...]

void __fastcall TfCalEst::Button1Click(TObject *Sender)
{
  try {
    ...

  } catch(Exception &Exc) {
    ...

    CreateControl( mOpcMenu->Tag);
 }

Tambíen revisa este artículo sobre el uso de return dentro de catch: Cosas para nunca hacer con C++ Builder

Saludos .)


La franja horaria es GMT +2. Ahora son las 19:16:09.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi