Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Mis preguntas sobre C++

Iniciado por tewe76, 08 de Febrero de 2009, 03:34:22 PM

« anterior - próximo »

davur

Cita de: tewe76 en 10 de Febrero de 2009, 12:00:04 PM
¿Es bueno crear una clase enorme (en cuanto a memoria, no en cuanto a miembros)? arkangel2803 ha dicho que no hay límite de tamaño para las clases, pero sí para las variables globales. Y, obviamente, si creo una clase madre es para crear una variable global de esa clase ???

No es bueno tener clases enormes, ni depender de variables globales. Principalmente porque dificulta el uso y mantenimiento del código. Respecto al tamaño,  como se ha comentado, si tienes una clase que contiene varios subsistemas como miembros, normalmente no los almacenas por valor, estáticamente, sino que mantienes punteros (inteligentes) a los mismos.

Cita de: tewe76 en 10 de Febrero de 2009, 12:00:04 PM
Pensaba que la pregunta era sencilla, pero veo que se complica, y no lo entiendo...
¿Vosotros no usáis un método tipo "Juego -> Render -> Dibujar" (es un ejemplo, no lo toméis al pie de la letra)? ¿Cómo lo implementáis?

Como lo implementes depende de muchas cosas. Pero siguiendo tu ejemplo, podrías tener algo como (muy a grosso modo, y con omisiones):

class IRenderer
{
public:
    void Render()
    {
        BOOST_FOREACH(boost::shared_ptr<IRenderable> renderable, renderable)
        {
            renderable->Render();
        }
    }

private:
    std::vector<boost::shared_ptr<IRenderable> > renderables;
};

class Game
{
public:
    void Render() { renderer->Render(); }

private:
    boost::shared_ptr<IRenderer> renderer;
};


Puedes ver que abunda la semántica de referencia, el tamaño no debería ser un problema en la mayoría de casos.

tewe76

CitarUna clase madre es simplemente una forma de agrupar código que es común a un conjunto de clases.
Seguramente mi expresión no es correcta, pero no me refería a una clase básica común de la que hereden las demás, sino a una clase desde la cual se accede a las demás.
CitarDe todas formas esa clase madre de la que hablas, pues no debería de ser más que un conjunto de punteros a los diferentes subsistemas de los que contará tu juego (lógica, vídeo, audio, ...) y un puñado de métodos. Así que no tendría que ocupar ni unos centenares de bytes de esos que te preocupan tanto.
CitarRespecto al tamaño,  como se ha comentado, si tienes una clase que contiene varios subsistemas como miembros, normalmente no los almacenas por valor, estáticamente, sino que mantienes punteros (inteligentes) a los mismos.
Ah, punteros... como nunca los he usado ::), no los tomaba en consideración, pero tenéis razón en lo que decís.
CitarComo lo implementes depende de muchas cosas. Pero siguiendo tu ejemplo, podrías tener algo como (muy a grosso modo, y con omisiones):
No entiendo del todo el código, pero creo que capto la idea.
Gracias a todos :)
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

tewe76

A ver, siguiendo el tetris de loover (anda que no le saco partido :P), he implementado lo que llevaba de mi engine y parece que funciona todo bien, pero os pongo un ejemplo simple de cómo lo hago para que me digáis si está bien:

class ClaseHija
{
public:
int DatoDeHija;
};

class ClaseMadre
{
public:
ClaseHija* HIJA;
};

int main()
{
ClaseHija MiHija; //creamos la Hija
ClaseMadre MiMadre; //creamos la Madre
MiMadre.HIJA=&MiHija; //"asociamos" el puntero de la Hija a la Madre
//Usos posibles:
//1:
MiMadre.HIJA->DatoDeHija=10;
//2:
MiHija.DatoDeHija=10;
}

(Nota: loover usa el constructor para hacer el "MiMadre.HIJA=&MiHija;", aunque a mí hacerlo así me resulta más intuitivo. Lo he probado de las dos formas y las dos van bien.)

Preguntas:
1- ¿Es correcto este método? Con que no sea una bestialidad me conformo ::)
2- Para acceder a DatoDeHija puedo usar cualquiera de los dos "Usos", ¿no? ("MiMadre.HIJA->DatoDeHija=10;" o "MiHija.DatoDeHija=10;")
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

shephiroth

#18
Este ultimo post no lo entiendo....clase madre y clase hija se llama cuando hay HERENCIA, es decir, la clase hija HEREDA de clase madre. En tu ejemplo una de las clases tiene como variable un puntero a la otra clase.....

No entiendo  ??? ???

Sobre las preguntas:
1- No es incorrecto (salvo que no entiendo el nombre de las clases)
2- Ambas son correctas. Lo mas normal es (en mi opinion) que tengas una clase principal con punteros a tus diferentes servicios(render, fisicas, etc, etc) y que tengas un puntero global a esta clase principal. Asi en el main la instancias y tienes acceso desde cualquier parte del proyecto.

davur

Todo es correcto, pero yo no expondría públicamente un puntero tan alegremente, porque cualquiera es libre de hacer lo que quiera con él.

tewe76

CitarEste ultimo post no lo entiendo....clase madre y clase hija se llama cuando hay HERENCIA, es decir, la clase hija HEREDA de clase madre. En tu ejemplo una de las clases tiene como variable un puntero a la otra clase.....
Ya, es que mi terminología es confusa :-[ . La llamo madre en el sentido de que contiene a todas las demás (como una nave nodriza contiene a las mininaves). En vez de Madre, llámala Primaria, y en vez de Hija, Secundaria.
Citar2- Ambas son correctas. Lo mas normal es (en mi opinion) que tengas una clase principal con punteros a tus diferentes servicios(render, fisicas, etc, etc) y que tengas un puntero global a esta clase principal. Asi en el main la instancias y tienes acceso desde cualquier parte del proyecto.
Es lo que estoy haciendo en el ejemplo EXCEPTO que para la clase principal uso un objeto, no un puntero al objeto (si es que te he entendido bien). ¿Qué ventaja tiene usar un puntero en vez de el objeto directamente? ???

CitarTodo es correcto, pero yo no expondría públicamente un puntero tan alegremente, porque cualquiera es libre de hacer lo que quiera con él.
¿Lo que propones es poner los punteros en el private (de Madre) y poner en el public (de Madre) unas funciones que devuelvan ese puntero privado? ¿Qué peligros puede tener dejar el puntero en public?
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

[EX3]

#21
Cita de: tewe76 en 12 de Febrero de 2009, 11:54:16 AM
CitarEste ultimo post no lo entiendo....clase madre y clase hija se llama cuando hay HERENCIA, es decir, la clase hija HEREDA de clase madre. En tu ejemplo una de las clases tiene como variable un puntero a la otra clase.....
Ya, es que mi terminología es confusa :-[ . La llamo madre en el sentido de que contiene a todas las demás (como una nave nodriza contiene a las mininaves). En vez de Madre, llámala Primaria, y en vez de Hija, Secundaria.
Yo no escribiria el codigo de las clases hijas dentro de la clase madre si no cada clase en su propio archivo. Asi te resulta mas facil ver a simple vista que clases tienes en el proyecto y te ayuda a localizar con facilidad el codigo concreto que buscas. Para lo de la jerarquia Madre -> Hija usa lo de los namespaces y te quitas de rollos. Esto te permite tener inclusive el mismo nombre para algunas clases en diferentes ambitos: una clase "Buffer" en el nombre de espacios de "Graphics" y otra en "Audio" por ejemplo.

Cita de: tewe76 en 12 de Febrero de 2009, 11:54:16 AM
CitarTodo es correcto, pero yo no expondría públicamente un puntero tan alegremente, porque cualquiera es libre de hacer lo que quiera con él.
¿Lo que propones es poner los punteros en el private (de Madre) y poner en el public (de Madre) unas funciones que devuelvan ese puntero privado? ¿Qué peligros puede tener dejar el puntero en public?
Yo en C# no tengo punteros (gracias a Dios  >:D) y esto lo solucione creando en la clase principal unas propiedades que devolvian la referencia a la instancia de la clase principal de cada area. Creo que en C++ se puede hacer igual, no?

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Titonus

Cita de: tewe76 en 12 de Febrero de 2009, 11:54:16 AM
CitarTodo es correcto, pero yo no expondría públicamente un puntero tan alegremente, porque cualquiera es libre de hacer lo que quiera con él.
¿Lo que propones es poner los punteros en el private (de Madre) y poner en el public (de Madre) unas funciones que devuelvan ese puntero privado? ¿Qué peligros puede tener dejar el puntero en public?

Para poder acceder a los miembros de la clase Madre desde una clase Hija puedes declararlos como protected, de esta forma seguirán siendo privados pero te permitirán no tener que crear las funciones que citas.

tewe76

CitarYo no escribiria el codigo de las clases hijas dentro de la clase madre si no cada clase en su propio archivo.
No es eso lo que estoy haciendo. Cada clase está declarada y definida por separado, pero en la clase madre (voy a intentar llamarla primaria a partir de ahora, para evitar más confusiones) incluyo unos punteros a dichas clases secundarias.
CitarPara lo de la jerarquia Madre -> Hija usa lo de los namespaces y te quitas de rollos.
Sí, es lo segundo que intenté, y funcionaba también... no sé, le veo pros y cons a los dos métodos, tengo que pensarlo mejor...
CitarYo en C# no tengo punteros (gracias a Dios  ) y esto lo solucione creando en la clase principal unas propiedades que devolvian la referencia a la instancia de la clase principal de cada area. Creo que en C++ se puede hacer igual, no?
No tengo la más remota idea ::) ;) Pero, ¿no me acabas de recomendar que use namespaces? ¿Para qué necesitas entonces clase principal?

CitarPara poder acceder a los miembros de la clase Madre desde una clase Hija puedes declararlos como protected, de esta forma seguirán siendo privados pero te permitirán no tener que crear las funciones que citas.
Ah, pensaba que te había entendido mal, pero eres tú el que me ha entendido mal a mí. Es que yo no quiero acceder a los miembros de la clase Madre desde una clase Hija (llamémoslas mejor Primaria y Secundaria), sino más bien al contrario: quiero que desde la Primaria pueda acceder a los datos de la Secundaria. Quiero y puedo, vamos, poniéndola en public me funciona bien.
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

Vicente

Cita de: tewe76 en 12 de Febrero de 2009, 04:17:58 PM
CitarYo en C# no tengo punteros (gracias a Dios  ) y esto lo solucione creando en la clase principal unas propiedades que devolvian la referencia a la instancia de la clase principal de cada area. Creo que en C++ se puede hacer igual, no?
No tengo la más remota idea ::) ;) Pero, ¿no me acabas de recomendar que use namespaces? ¿Para qué necesitas entonces clase principal?

Teweee, que son cosas diferenteeeeeeeeees y totalmente compatibles!

tewe76

Sí, pero... -- da igual, me empieza a doler la cabeza ::)
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

[EX3]

#26
Una clase principal para mi es una clase que gestiona operaciones de las anteriores y administra las copias e instancias que hagas de las hijas, por ejemplo, una clase principal de graficos, render o manager en mi caso, deberia ser quien gestione una coleccion de instancias de clases textura. La clase render o manager seria la clase madre del espacio de nombres de graficos y la clase textura seria una clase hija del espacio de nombres de graficos, una jerarquia, vamos. El espacio de nombres agruparia las clases pertenecientes a graficos y la clase madre seria el foco principal de operaciones del area de graficos.

Citar
CitarPara poder acceder a los miembros de la clase Madre desde una clase Hija puedes declararlos como protected, de esta forma seguirán siendo privados pero te permitirán no tener que crear las funciones que citas.
Ah, pensaba que te había entendido mal, pero eres tú el que me ha entendido mal a mí. Es que yo no quiero acceder a los miembros de la clase Madre desde una clase Hija (llamémoslas mejor Primaria y Secundaria), sino más bien al contrario: quiero que desde la Primaria pueda acceder a los datos de la Secundaria. Quiero y puedo, vamos, poniéndola en public me funciona bien.
Si tienes una clase principal en el motor cuya instancia sea estatica (una clase estatica, vamos), esta la puedes acceder desde cualquier parte del codigo. Si en esa clase principal del motor tienes accesos definidos a las clases principales de las areas que defina el motor: graficos, audio, etc..., una clase textura podria acceder asi a las propiedades de la clase madre de graficos, aunque esto no deberia darse ya que la clase textura no deberia por que llamar a la madre, no se si me explico, seria la clase madre quien deberia tener acceso a las clases hijas, algo parecido a lo de programar por capas.

Estas historias de la POO tratalas con paciencia. Aqui donde me ves aun soy novato en este tipo de programacion (practicamente desde que toco .NET) y se que cuesta hacerse a ello despues de largos años programando en BASIC :P Con la practica es como veras las ventajas y los inconvenientes de hacer las cosas de una manera u otra.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

davur

#27
Cita de: tewe76 en 12 de Febrero de 2009, 11:54:16 AM
¿Lo que propones es poner los punteros en el private (de Madre) y poner en el public (de Madre) unas funciones que devuelvan ese puntero privado? ¿Qué peligros puede tener dejar el puntero en public?

No necesariamente, depende de lo que necesites. Normalmente, si tienes:

struct Foo
{
    Bar* bar;
};


Nada impide que, dado un objeto f de tipo Foo, alguien haga:

f.bar = NULL;

O algo igualmente peligroso. Peligroso porque rompe la invariante de tu clase (que bar apunte a un objeto de tipo Bar válido), y entre otras cosas te obliga a comprobar que bar es distinto de NULL cada vez que necesitas utilizarlo. Compáralo a:

class Foo
{
public:
    Foo(Bar& b) : bar(&b) { }

    const Bar& GetBar() const { return *bar; }
    Bar& GetBar() { return *bar; }

private:
    Bar* bar;
};


Por poner un ejemplo, aunque no es idiomático utilizar punteros llanos en C++. Dependiendo de si la clase en cuestión asume la propiedad exclusiva o compartida de la memoria que se le pasa, se utiliza un tipo de puntero inteligente u otro.

Cita de: tewe76 en 12 de Febrero de 2009, 11:54:16 AM
¿Qué ventaja tiene usar un puntero en vez de el objeto directamente? ???

¿Cómo es posible hacer referencia desde varias clases a un mismo objeto de otra clase sin utilizar punteros o referencias?

tewe76

CitarEstas historias de la POO tratalas con paciencia.
En éso estamos... ::)

A davur:
Me temo que mi nivel de C++ no me permite entenderte ::) . El problema sí lo entiendo, aunque no lo veo muy preocupante. Y la solución la capto a nivel general, pero no consigo implementarla.

Si os parece bien, por mi parte cierro ya el tema de Clases, Namespaces y similares. Por ahora voy a usar el método que he explicado en el ejemplo, que me va bien y es bastante intuitivo :) .

Seguro que vuelvo pronto con más dudillas. Taluego ;)
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

Mars Attacks

Maldita sea, tewe, léete el libro de 800 páginas y deja de enredar. Tardarás mucho menos en volver con las preguntas realmente interesantes.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.