Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problema con funciones virtuales, se llama a la que no és.

Iniciado por tamat, 03 de Enero de 2009, 02:55:05 PM

« anterior - próximo »

tamat

Tengo una clase que deriva de otra, que a su vez deriba de otra:

Texture -> Reource -> Object

El problema surge cuando instancío texture y llamo a un método virtual de texture (que no tienen sus padres) llamado Create, entonces el visual me avisa de que algo raro está pasando porque la pila no encaja bien, entonces debugo y veo que efectivamente al llamar a mi método virtual se me está ejecutando un método totalmente distinto, no el mismo método en la clase padre, directamente uno con parametros y retorno diferente, que obviamente me está dejando la pila hecha un cristo y el visual se da cuenta al ver que no encaja el numero de bytes allocados.

Bien, hasta aquí yo podría pensar - en algun momento he jodido la tabla de funciones virtuales al salirme de algun array o hacer un memset - pero realmente no hay nada raro, creo la instancia, y lo siguiente que hago es llamar al metodo virtual, y los constructores son muy simples, solo ponen a cero las variables (no uso nunca memcpys o memsets, directamente igualo a cero).

Desesperado se me ocurre heredar de Texture una clase Foo, instanciarla y llamar a mi metodo virtual Create, y entonces sí funciona. O sea que Foo sí que deja bien la tabla de funciones virtuales, Texture no.

Intento debugar la tabla para ver si en algun momento se cambia pero en mi tabla de funciones virtuales no sale mi método Create, salen solo los de la clase padre, supongo que el compilador si ve que un metodo no tiene dos implementaciones entonces se ahorra reservarle espacio en la tabla de funciones.

En fin, es desesperante y llevo ya un día perdido con esta chorrada, debería intentar aislar el problema pero es una clase enorme que usa todo mi framework y está jodido.

Si alguien tiene alguna idea se lo agradeceré (aunque como alguien me venga con - has puesto la palabra virtual delante del nombre de la funcion? - me pondré muy tenso... y no quereis que me ponga tenso)
Por un stratos menos tenso

Mars Attacks

#1
¿Qué ocurre si eliminas la cabecera de la función virtual Create? ¿Se queja el compilador? (Dicho de otra forma: ¿encuentra la función aunque no la hubieras declarado?)

Segunda idea: ¿Qué ocurre si añades a los padres la función virtual Create vacía? ¿Sigue funcionando mal?

AK47

Estas usando punteros o referencias de las instancias, o estas usando las instancias directamente? Pon el codigo relevante del problema, anda :)

tamat

Respondiendo a Mars:

Si quito la funcion peta el compilador, no tiene pinta de usar otra funcion, de hecho probé de cambiarle el nombre no sea que por Create pillase algo de windows, pero hacía lo mismo

Lo de ponerle la funcion a los padres lo pensé pero por desgracia algunos parametros son enums de la clase Texture así que está dificil, pero lo intentaré cambiando algunas cosas.

Respondiendo a AK:

Uso punteros, podría poner el codigo pero no vereis nada raro, es todo muuuy estandar, por ejemplo:



class Texture : public Resource
{
//...
virtual const char* tellmefoo() { return "foooo!"; }
virtual const char* ozu(int a,int b,int c) { return "foooo2!"; }
};

//...
Texture* texture = new Texture();
texture->ozu(1,2,3);



Al debugar la llamada a ozu veo que entra en tellmefoo.

En fin, entiendo que es un error rarisimo en el que pueden afectar mil cosas, es solo que ha aparecido de la nada y me tiene algo desesperado, tendré que reducirlo a lo minimo... pero joder, para unas navidades que tenía tiempo para programar y me las paso en esta mierda...

Gracias por las respuestas
Por un stratos menos tenso

tamat

Puestos a aislar he creado esta mini aplicacion donde sucede el error, así que paso a remirar linea a linea los constructores (por eneaba vez)

#include <iostream>

#include "HH.hxx"

void main()
{
HH::Texture* t = new HH::Texture;
t->ozu(1,2,3); //<-- Llama a tellmefoo();
}
Por un stratos menos tenso

Buffon

Perdona si no he entendido bien el código pero, para que usas virtual en la hija ?

virtual es para definir una función que va a ser polimórfica, así la clase será tratada como abstracta y no referenciable y se ponen en los padres, si la defines en el hijo no tiene uso o significado.

tamat

tal vez porque alguien hereda de Texture y reimplementa ese método... como RenderTexture. En serio, no busco consejos sobre POO, llevo muchos años en el gremio
Por un stratos menos tenso

gdl

En lo que pones no veo nada raro, pero por decir algo que suele ser usual: Las funciones virtuales no se pueden llamar desde los constructores. Lo mismo no es eso, pero para ir  descartando cosas.

tamat

sip, eso está descartado, de hecho ningun constructor llama a ninguna función.

Pero no le deis vueltas, suena a error muchungo, regiones de memoria que se solapan, algo así, cuando lo descubra ya os lo diré, pero era por saber si alguien había experimentado algo parecido.
Por un stratos menos tenso

AK47

Poner una funcion a virtual no hace que la clase sea abstracta y no se pueda instanciar, eso solo pasa con las funciones virtuales puras (esos con virtual tralari = 0)

tamat

pero si aquí nadie está hablando de clases virtuales puras, leñe. Que esto no es un thread de - enseñanos cuanto sabes de POO - sino sobre errores chungos con la tabla de punteros a funciones virtuales.
Por un stratos menos tenso

Pogacha

Has una copia del proyecto entero y ve borrando partes que creas no intervengan, cuando deje de hacer la falla te fijas que cambiaste ultimo.



tamat

eso he intentado, pero está dificil porque es un proyecto con demasiadas dependencias. Para colmo he hecho un miniproyecto que usa el framework y al ejecutar me pide la opengl.dll cuando nunca me había pedido esa dll (siempre me pedía la opengl32.dll), alguien sabe qué diferencia hay? yo linko contra opengl32.lib así que no entiendo a qué viene opengl.dll
Por un stratos menos tenso

davidgf

Tienes la posibilidad de probar con otro compilador? Ni que fuera una versión distinta del visual.

Saludos!
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

HarvesterOfAcorns

Has declarado tus clases en un espacio de nombres? Lo pregunto porque se me ocurre una hipótesis pelín peliaguda, pero dado lo chungo del asunto no estaría de más descartar.

A ver, supongamos que en alguno de los archivos de cabecera que hayas incluido en tu proyecto, digamos alguno de opengl, se define una clase con el mismo nombre que la tuya, Texture, supongamos, y van dos, que alguna de las constructoras de esa clase de ogl admite los mismos argumentos que la constructora de tu clase Texture; supongamos, que pesadito!!!, que esa clase implementa un método que se llama ozu(), esto ya sería la leche de la coincidencia, y por último vamos a suponer que ese método ozu() ejecuta otro método de su misma clase cuando se le llama, supón que es un método privado, y que se llama tellmefoo(), la releche!!!!

Al crear una instancia de Textura el compilador debería cuando menos avisar de que hay dos clases con el mismo nombre y que no sabe a cual te estás refiriendo, salvo que en alguna parte del código haya alguna instrucción del tipo "using namespace espacio_opengl" que le indique al compilador que la clase Texture que ha de instanciar  no es la tuya sino la de ogl.

Además esto también podría explicar el problema de  las dll.

Bueno, ya avisé que era descabellado, igual me he pasao.







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.