Acceso a mienbros no estaticos de clase a traves de estaticos

Iniciado por setupybios, 24 Septiembre 2014, 16:25 PM

0 Miembros y 1 Visitante están viendo este tema.

setupybios

Hola amigos, me ha surgido una gran duda y quería compartirla para ver si alguien que la tenga clara me puede abrir el horizonte. Resulta que estoy trabajando con un framework para realizar juegos, y he visto que ocupan mucho lo que voy a explicar a continuación, que por lo visto es valido porque compila sin problemas y además anda bien y me esta funcionando, sin mas preámbulos paso a explicar mi duda.
Tengo una clase llamémosla X , que hereda de la clase que la vamos a llamar Y, resulta que la clase X tiene un método estatico, y mi duda es la siguiente: por medio de ese método estatico pueden acceder a cualquiera de los métodos no estáticos de las dos clases e invocarlos. Lo pongo con código para que se entienda mejor, no entiendo como es esto posible. Como ese método estatico permite apuntar e invocar a cualquier método no estatico de las clases.

Código (cpp) [Seleccionar]
#ifndef __CC_EGLVIEW_ANDROID_H__
#define __CC_EGLVIEW_ANDROID_H__

#include "cocoa/CCGeometry.h"
#include "platform/CCEGLViewProtocol.h"

NS_CC_BEGIN

class CC_DLL CCEGLView : public CCEGLViewProtocol
{
public:
   CCEGLView();
   virtual ~CCEGLView();

   bool    isOpenGLReady();

   // keep compatible
   void    end();
   void    swapBuffers();
   void    setIMEKeyboardState(bool bOpen);
   
   // static function
   /**
   @brief    get the shared main open gl window
   */
   static CCEGLView* sharedOpenGLView(); METODO ESTATICO
};

NS_CC_END

#endif    // end of __CC_EGLVIEW_ANDROID_H__



Y HACEN COSAS COMO ESTAS CON ESTE METODO ESTATICO

Código (cpp) [Seleccionar]
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll);
EN DONDE  EL METODO setDesignResolutionSize() ES UN METODO NO ESTATICO DE LA CLASE BASE CCEGLViewProtocol. NO ENTIENDO COMO SE APUNTA . CCEGLViewProtocol es la clase base y  tiene el método setDesignResolutionSize que lo puedo invocar por medio de un método estatico de la clase derivada CCEGLView.
Bueno espero q me tiren un salvavidas asi puedo entender mejor lo que esta sucediendo. Gracias Javier.

eferion

Bienvenido al foro.

En primer lugar, sería conveniente que editases el mensaje y decorases el código con las etiquetas GeSHi para mejorar su legibilidad.

Dicho esto, vamos a intentar resolver tu duda.

Vamos a simplificar el entorno. Imagina que tenemos esta clase:

Código (cpp) [Seleccionar]

class POO
{
  public:

    int dato( );

    static POO* MetodoEstatico( );
};


con esta clase tu podrías tener un código tal que:

Código (cpp) [Seleccionar]
std::cout << POO::MetodoEstatico( )->dato( );

Y la pregunta es ¿Por qué? ¿Cómo funciona? Muy sencillo.

Si te fijas, el método estático devuelve un puntero a una clase de tipo POO, lo que estás haciendo es recuperar ese puntero y acceder a los miembros de la instancia apuntada por dicho puntero. El código que te he puesto antes se puede descomponer para facilitar su lectura

Código (cpp) [Seleccionar]

POO* puntero = POO::MetodoEstatico( );
std::cout << puntero->dato( );


Este tipo de estructura se usa mucho al programar Singleton, que sirve para asegurarse de que sólo existe una instancia de una clase concreta... una forma de implementar un sigleton es la siguiente:

Código (cpp) [Seleccionar]

class Singleton
{
  public:

    int dato( )
    { return _dato; }

    static Singleton* Instance( )
    {
      static Singleton* instance = new Singleton( );
      return instance;
    }

  private:

    // Los constructores son privados para impedir que se creen nuevas instancias
    Singleton( )
    { _dato = 1; }

    // El constructor copia no hace falta implementarlo, con declararlo como privado vale
    Singleton( const Singleton& );

    // Al operador de asignación le pasa lo mismo, no hace falta implementarlo.
    Singleton& operator=( const Singleton& );
};


Obviamente, desde un método estático no se pueden llamar a miembros no estáticos de la clase, el siguiente código no compila:

Código (cpp) [Seleccionar]

class POO
{
  public:

    int dato( )
    { return _dato; }

    static int MetodoEstatico( )
    { return dato( ); }
};


No se si con esto he resuelto tu duda, espero que sí.

Un saludo.

setupybios

Gracias, muchas gracias eferion, me sacaste la venda de los ojos, tenia la respuesta frente a mi, pero a veces si no te lo explica otra persona uno no cae en la cuenta. Entonces lo que hace el metodo estatico es devolver el puntero de la clase es por eso que puedo acceder a los metodos no estaticos sin tener una instancia de la clase. Yo buscaba algo mas complicado pense que de alguna manera cuando compilaba el compilador sabia que el metodo estatico apuntaba a la clase (ya que la clase puede no estar instanciada y no existir ningun objeto de esa clase). Es justo lo que buscaba y si el framework con el que trabajo tiene solo una copia de ciertas clases no sabia que se llamaba programacion Singleton, voy a leer un poco mas acerca de esto. Saludos Javier.

setupybios

eferion al analizar el codigo mas detenidamente y ahora entendiendolo deduzco que cuando yo llamo al metodo no estatico por medio del estatico, estoy ejecutando tambien el metodo estatico (o sea que si el metodo estatico modifica alguna variable o hace algo en ese momento lo estaria haciendo) esto lo deduzco porque si devuelve un puntero a la clase es porque se ejecuto el metodo estatico, ES ASI COMO PIENSO?

Código (cpp) [Seleccionar]
std::cout << POO::MetodoEstatico( )->dato( );

en este caso primero ejecuta MetodoEstatico para poder tener el puntero, y despues estaria ejecutando dato().

Gracias Javier.

eferion

La línea que has puesto:

Código (cpp) [Seleccionar]
std::cout << POO::MetodoEstatico( )->dato( );

Se descompone en estas otras líneas de código:

Código (cpp) [Seleccionar]

Prueba* temp = POO::MetodoEstatico( );
int valor = temp->dato( );
std::cout << valor;


Luego, efectivamente, primero se accede a "MetodoEstatico". Este método devuelve un puntero a un objeto de tipo "POO". Después se recupera el valor devuelto por el método "dato" de dicho objeto y, finalmente, se imprime el valor en pantalla.