Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   hacer a->b->c(); con una clase (https://www.clubdelphi.com/foros/showthread.php?t=86178)

aguml 27-06-2014 08:52:26

hacer a->b->c(); con una clase
 
hola amigos, tengo una clase en la que habrá métodos y quiero que por ejemplo haya una estructura con mas metodos. Por ejemplo, la estructura int que contenga a tofloat, tohex, y tobin. Entonces, poder hacer clase->int->tobin(); ¿Como hago eso? Se me ocurrio crear esos metodos como privados y luego crear una estructura dentro del public con punteros a esos metodos pero no se si es correcto y si se podria hacer.

escafandra 27-06-2014 13:38:05

Código:

class TInt
{
  private:
  int I;
  public:
  float ToFloat();
  char  ToHex();
};

class TClase
{
  public:
  TInt Int;
  float ToFloat();
  char  ToHex();
};

//........................................
 
void funcion()
{
  TClase C;
  C.Int.ToFloat();
}



Saludos.

aguml 27-06-2014 17:10:34

bueno ¿Y si la clase que contiene las funciones tiene que poder trabajar con variables y objetos que estan declarados en el private de la otra clase? Ese es el caso concreto. Ya lo he conseguido pero en vez de usar otra clase he creado una estructura en el public de la clase y en esa estructura hay punteros a los metodos, los cuales se declaran en el private de la misma clase. Para poder hacer que se trague esto tuve que usar __closure* que no se ni que es. Tambien en el constructor de la clase asigno a los punteros los metodos que tengo definidos. Luego cuando llegue a casa pongo lo que hice a ver si te parece correcto o no. Solo un detalle y esque cuando hago uso de la funcion, al escribirla me aparece en lalista y le doy pero aparece sin parentesis al final y se lo tengo que poner yo junto con el parametro.

aguml 27-06-2014 20:53:42

Bueno ya estoy por casa. Al final he guardado el que usa __closure porque funciona pero estoy intentando arreglarlo asi:

En el constructor:
Código:

TPrueba::TPrueba()
{
    //Creo la estructura
    Conversion = new TIPOS;

    //Inicializacion de las funciones de la estructura para los Anti-Anti-Debug
    Conversion->toFloat = &toFloat;
    Conversion->toBin = &toBin;
}

En el public de la clase:
Código:

//Declaracion del tipo de estructura para los Anti-Anti-Debug
struct TIPOS{
        AnsiString __fastcall (TPrueba::*toFloat(int));
        AnsiString __fastcall (TPrueba::*toBin(int));
}*Conversion;

En el private tengo esto:
Código:

AnsiString __fastcall toFloat(int);
AnsiString __fastcall toBin(int);

En el .cpp de la clase tengo esto:
Código:

AnsiString __fastcall TPrueba::toFloat(int value)
{
    return "";
}
//---------------------------------------------------------------------------

AnsiString __fastcall TPrueba::toBin(int value)
{
    return "";
}

Y por ultimo en el Unit1.cpp tengo esto:
Código:

Prueba  = new TPrueba();

AnsiString Float = Prueba->Conversion->toFloat(1000);
AnsiString Bin = Prueba->Conversion->toBin(1000);

Y el error que me está dando es este:
Código:

[C++ Error] TPrueba.cpp(16): E2235 Member function must be called or its address taken
[C++ Error] TPrueba.cpp(17): E2235 Member function must be called or its address taken

Me pone en rojo la zona donde asigno el miembro al puntero, en el constructor.

aguml 28-06-2014 15:20:03

Esto funciona pero usa __closure: http://pastebin.com/czvfhEj8
Ya que hago algo me gustaria hacerlo lo mas correcto posible. Podria declarar sin problema los metodos como publicos y no tendria problemas ni tendria que crear una estructura o clase ni nada pero estarián desordenados, o sea, no podria crear un orden como el que he creado ahi. O sea, que si voy a trabajar con cadenas pues al poner un -> me salgan todos los metodos para cadenas, si voy a trabajar con enteros pues que al poner el -> que me salgan solo los que sirvan para enteros y asi con todo. Mas o menos lo que hace Builder cuando haces un Edit1->Text.sprintf("%i",9) que como ves te muestra la funcion sprintf.

aguml 28-06-2014 18:51:16

Lo ultimo que he probado pero no soy capaz de hacerlo compilar es esto: http://pastebin.com/4Pd9DYEr
El problema lo tenemos en la funcion miembra de TInt que no soy capaz de asignar el valor de entrada a la direccion donde apunta el puntero ni tampoco mostrar su valor.

aguml 28-06-2014 20:04:46

Perdon por escribir tanto pero en realidad lo que necesito hacer es esto:
Código:

class TPrueba; //Declaro la clase TPrueba
 
  class TInt
  {
        public:
                //Constructor y destructor
                TInt();
                ~TInt();
 
                //Declaraciones de las funciones para TInt
                AnsiString toHex(int value);
        private:
                THilo* TPrueba::*Hilo; //Declaro el puntero a miembro
  };
 
  //La clase TPrueba
  class TPrueba
  {
        friend class TInt; //Pongo esto para que pueda acceder al puntero al TThread que está en private
 
        public:
                TPrueba();
                ~TPrueba();
        private:
                THilo *Hilo; //Puntero a TThread
}
 
//Constructor de la clase TInt
TInt::TInt()
{
        Hilo = &TPrueba::Hilo; //Le asigno la direccion del miembro TPrueba al puntero a miembro de la clase TInt
}
 
//Funcion miembro de la clase TInt que usa el puntero a miembro que creé
AnsiString __fastcall TInt::toHex(int value)
{
        //Esto no lo quiere:
        ((THilo *)->Hilo)->toHex(value);
        //He probado de todo pero no doy con el modo
}

No es mas que un ejemplo pero creo que ahora se entenderá mejor. Necesito hacer que funcione lo que está en la funcion miembro.

escafandra 29-06-2014 13:04:16

Creo que te complicas la vida perdiéndote en la sintaxis. No puedes pensar en determinada solución sintáctica para enfocar el problema en esa dirección sino al revés. En esos ejemplos no queda claro cual es el planteamiento del problema que quieres resolver pro lo que no puedo orientarte bien.

Si te puedo decir que las clases con punteros hay que manejarlas muy bien o tendrás problemas difíciles de depurar.


Esto:
Código:

((THilo *)->Hilo)->toHex(value);
No puede compilar, ni tiene sentido. Un cast no es una clase. ¿Cual es la definición de Hilo?
Piensa en usar clases derivadas.


Saludos.

aguml 29-06-2014 13:49:28

pero ¿las clases derivadas no heredan todo de la clase que deriban? No quiero eso exactamente. Hilo es un tthread que es privado en la clase TPrueba y lo que quiero es que la clase TInt pueda manejar el mismo hilo que haya creado TPrueba. Me han comentado que cree una estructura donde meta la declaracion de una funcion virtual que actue como callback y luego haga algo como clase TPrueba : private Estructura y dentro de TInt cree un metodo que use ese callback para acceder al hilo pero me pierdo y no se como hacerlo y ademas tanto la funcion callback como la que haga uso de ella tendrian que ser privadas ya que ambas usarian punteros a la estructura o a la clase. Tengo un cacao mental que ya no me entero de nada.

escafandra 30-06-2014 01:34:16

Cita:

Empezado por aguml (Mensaje 478459)
pero ¿las clases derivadas no heredan todo de la clase que deriban? No quiero eso exactamente.

Si, pero en C++ existe la herencia múltiple.

Cita:

Empezado por aguml (Mensaje 478459)
Me han comentado que cree una estructura donde meta la declaracion de una funcion virtual que actue como callback

Las funciones miembro virtuales sólo tienen sentido en las clases derivadas de la madre en la que se declara una función virtual y deber reescribirlas en sus derivadas.

Cita:

Empezado por aguml (Mensaje 478459)
y luego haga algo como clase TPrueba : private Estructura y dentro de TInt cree un metodo que use ese callback para acceder al hilo pero me pierdo

Un objeto de la clase Hilo sólo puede hacer uso de sus funciones miembro, objetos de clases amigas y de funciones generales, globales, que no pertenezcan a ninguna clase. Quizás esta última sea la solución mas acertada:
Código:

toHex(Hilo->value);

Saludos.

aguml 30-06-2014 09:37:59

bueno hilo seria un objeto y no una funcion ¿Me estas diciendo que hacerlo global seria la mejor solucion?

aguml 30-06-2014 15:40:01

Bueno lo he conseguido pero no se si es muy ortodoxo o no. Lo que he hecho es esto:
En TInt.h:
Código:

#ifndef Inth
#define Inth
//---------------------------------------------------------------------------

#include "THilo.h"

//---------------------------------------------------------------------------

//Declaracion de la clase
class TInt
{
        public:
                TInt(THilo *H);
                ~TInt();

                AnsiString __fastcall toHex(int value);
                AnsiString __fastcall toBin(int value);

        private:
                THilo *Hilo;

};
//---------------------------------------------------------------------------
#endif

En el TInt.cpp tengo esto:
Código:

#include "TInt.h"

TInt::TInt(THilo *H)
{
        Hilo = H;
}
//---------------------------------------------------------------------------

AnsiString __fastcall TInt::toHex(int value)
{
        AnsiString retval = "";
        __try{
                if(Hilo != NULL)
                        retval = Hilo->FuncToHex(value);
        }catch(...){
        }
        return retval;
}
//---------------------------------------------------------------------------

AnsiString __fastcall TInt::toBin(int value)
{
        AnsiString retval = "";
        __try{
                if(Hilo != NULL)
                        retval = Hilo->FuncToBin(value);
        }catch(...){
        }
        return retval;
}

En el TPrueba.h tengo esto:
Código:

#include <vcl.h>

#ifndef PRUEBAH
#define PRUEBAH
#include "TInt.h"

  class TPrueba
  {
        public:
        TPrueba();
                ~TPrueba();
                void __fastcall IniciarHilo(void);
                TInt *Int;

        private:
                THilo *Hilo;

  };
#endif

En el TPrueba.cpp tengo esto:
Código:

TPrueba::TPrueba()
{

}
//---------------------------------------------------------------------------

TPrueba::~TPrueba()
{
        delete Int;
        Int = NULL;
}
//---------------------------------------------------------------------------

void __fastcall TPrueba::IniciarHilo(void)
{
    //Creo el hilo
        Hilo = new THilo(true);

        if(Hilo == NULL)
        {
                MessageBox(Application->Handle,
                          "No se ha podido crear el hilo correctamente.\n Cierre la aplicación e intentelo de nuevo.",
                          "Error",
                          MB_OK | MB_ICONERROR | MB_APPLMODAL);
        }
        else{
                //Creo la otra clase
                Int = new TInt(Hilo);
        }
}

y en el Unit1.cpp tengo esto:
Código:

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        try{
        prueba  = new TPrueba();

    }
    catch(...){
    }
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        ShowMessage(prueba->Int->toHex(100));
        ShowMessage(prueba->Int->toBin(100));
}

Hilo no hace falta que lo ponga aquí porque el problema era acceder a el desde otra clase donde no estaba declarado y asi lo he podido solucionar ¿que os parece esta solucion? ¿chapuza? ¿correcta?

escafandra 30-06-2014 18:38:37

Sin conocer cual es el problema a resolver es muy difícil aconsejarte sobre como dar una solución orientada a objetos.

No indicas nada de Hilo, supongo que se destruye bien.
Sólo en las clases derivadas de VCL deben crearse los objetos como punteros. C++ puede crear objetos con sólo declararlos lo que es más sencillo y directo pero precisan que escribas un constructor por defecto o pases los parámetros apropiados. Por ejemplo:

Código:

THilo *Hilo = new THilo(true)
TInt Int(Hilo);

ó

Código:

TInt Int(new THilo(true));
La el diseño de las clases depende del problema a resolver y las perspectivas de reutilización de código.
Un mal diseño hará que el código sea poco eficiente y difícil de entender y depurar. En este sentido no puedo decirte si es la mejor solución a tu problema, o al menos lo que yo haría, que no tiene por que ser mejor que tu solución.

Saludos.

aguml 30-06-2014 22:06:40

THilo es del tipo TThread y es creado y destruido correctamente. Otra cosa ¿Existe alguna herramienta que conozca que te indique si tiene fallos como que uses new y luego no lo destruyas con delete? Creo que alguien hizo una herramienta que hacia algo asi sobr el binario aunque no lo probé.

escafandra 30-06-2014 22:38:41

Memory leak.

En el foro se ha hablado del tema.

Saludos.

aguml 01-07-2014 10:18:41

lo unico que encontré en el foro fue esto: http://www.clubdelphi.com/foros/show...ghlight=fastmm y es sobre delphi. Tengo entendido por lo que he podido leer que fastmm funciona en builder pero estoy buscando informacion al respecto de esas aopciones que hablan pero en español no encuentro nada. Tambien he visto que se habla de codeguard pero tampoco lo veo nada claro y nada en español.

escafandra 01-07-2014 11:18:26

Capturar un memory leak


Saludos.

aguml 01-07-2014 12:00:38

pues despues de todo lo leido creo que el mejor es eurekalog aunque es de pago.


La franja horaria es GMT +2. Ahora son las 18:32:43.

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