Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: DraKKaR en 10 de Agosto de 2004, 06:06:31 PM

Título: Problemilla Con Función Virtual.
Publicado por: DraKKaR en 10 de Agosto de 2004, 06:06:31 PM
 Estoy teniendo un problema flipante con el tema de una función virtual. Me explico. Esta mañana he añadido a la clase Camera de mi motor una función virtual, con ánimo de que sea implementada por clases que hereden de ella. Para renderizar el mundo, le paso una referencia a esta clase a la función de render para que sepa desde donde hacer el render. El problema está en que hay algo que no funciona, y el render que muestra no tiene sentido.

Para intentar ilustrar el problema. Partimos de una versión del código fuente que va perfectamente. A partir de ese momento únicamente le añado a la clase Camera la función virtual Abracadabra (o el nombre ke sea). Y ya esta! el programa va mal!. Lógicamente nadie llama a esa función. EL propblema viene simplemente de añadir a la clase una función de este tipo:


virtual void alksdufgkasdhfg(void){}


Eso ya hace que le prorgama se comporte de forma extraña. ¿Que tipo de problemas puede causar esto? Nadie llama a esta función y ninguna clase hija la reimplementa.

Necesito ver la luz!.

PD: Cada dia me gusta más C++.
Título: Problemilla Con Función Virtual.
Publicado por: Zaelsius en 10 de Agosto de 2004, 07:05:58 PM
 Sólo se me ocurren 2 cosas:

- O el compilador mete la pata..

- O antes hacías cosas "poco seguras" con punteros de clase y suponias ciertas cosas que ahora al tener una estructura interna diferente no son válidas... (no sé si me explico bien).
Título: Problemilla Con Función Virtual.
Publicado por: Haddd en 10 de Agosto de 2004, 07:10:09 PM
 Puede ser que copies clases utilizando memcpy. Sé que suena a locura, pero yo a veces lo he hecho  B)

Título: Problemilla Con Función Virtual.
Publicado por: synchrnzr en 10 de Agosto de 2004, 08:54:48 PM
 ¿Ya lo recompilas todo? El VC++ no acostumbra a recompilar los objetos cuando sólo cambias los .h y no los .c o .cpp (es por dar alguna idea...)

sync
Título: Problemilla Con Función Virtual.
Publicado por: DraKKaR en 10 de Agosto de 2004, 10:22:20 PM
 Gracias a todos por responder.

Zaelsius:
Citar
O el compilador mete la pata..
Es lo que me estoy temiendo...

Citar
O antes hacías cosas "poco seguras" con punteros de clase y suponias ciertas cosas que ahora al tener una estructura interna diferente no son válidas... (no sé si me explico bien)

Creo que te refieres a lo que dice, por ejemplo, Haddd mas abajo. Aun que fuera eso, añadir una función no incrementa el tamaño de una clase, ¿no?



Haddd:

CitarPuede ser que copies clases utilizando memcpy. Sé que suena a locura, pero yo a veces lo he hecho

Pero, añadir una función no incrementa el tamaño de una clase, ¿no? De todas formas lo revisaré por si acaso.



synchewrjkgnrg:
Sí todo recompiladito al hacer cada cambio, por si acaso.. (yo tb me conozco las artimañas  de mi viejo VC6)
Título: Problemilla Con Función Virtual.
Publicado por: DraKKaR en 10 de Agosto de 2004, 11:15:06 PM
 Esto es increible! He estado corrigiendo cosas por otra parte y ahora va y funciona la cosa! Pero las cosas que he corregido no pueden tener nada que ver con el problema, ya que no usaba punteros ni nada. Bueno, me parece que nunca sabré si el fallo era que el compilador se habia armado un lío, o es que tengo algún tipo de leak o puntero loko (cosa que dudo, uso donde puedo la template shared_ptr<>).

Buenos, gracias por la ayuda de todos modos.
Título: Problemilla Con Función Virtual.
Publicado por: StraT en 10 de Agosto de 2004, 11:49:00 PM
 Quizas cambiar otras cosas ha añadido cambios significativos al codigo y ha provocado una recompilacion completa. Se de cosas asi en dev c++, en visual c ni pu, :S

Un saludo
Título: Problemilla Con Función Virtual.
Publicado por: Mars Attacks en 11 de Agosto de 2004, 02:41:27 AM
 Si te sirve de consuelo, en mi práctica de sockets si declaraba unas variables de esta forma:

char mi_pene_es_azul[4080];
int furcia, ethernet_sucks;

sin usar *REPITO* sin usar para nada mi_pene_es_azul, el programa compilaba e iba bien.

Si, por el contrario, hacía

int furcia, ethernet_sucks;
char mi_pene_es_azul[4080];

sin usar *REPITO* sin usar para nada mi_pene_es_azul, el programa compilaba pero no hacía lo que debía.

Misteriosos misterios los de los compiladores...
Título: Problemilla Con Función Virtual.
Publicado por: ethernet en 11 de Agosto de 2004, 09:04:17 AM
 Mars, eso es _____obviamente_____ que te estabas pasando de madre en un vector, puntero o llamalo como quieras y al cambiar el vector de posicion se declara en la pila antes o despues con lo cual al pasarte, si esta antes, no modificas posibles valores importantes para la ejecucion...

con respecto a lo del post original: c++ tiene unos bonitos cast que se deben usar. Si lees effective c++ te dicen que no uses _NUNCA_ los cast de C. Desde mi punto de vista creo q es algo asi, un jueguecito con un puntero o un cast mal hecho
En ejemplo de lo que pienso que puede pasar:




#include <iostream>

struct A
{
virtual void a()
{
 std::cout << "A::a" << std::endl;
}
virtual void b()
{
 std::cout << "A::b" << std::endl;  
}
};

struct AA:public A
{
virtual void a()
{
 std::cout << "AA::a" << std::endl;
}
virtual void b()
{
 std::cout << "AA::b" << std::endl;  
}

};

struct B
{
virtual void b()
{
 std::cout << "B::b" << std::endl;
}
virtual void a()
{
 std::cout << "B::a" << std::endl;  
}
};

int main()
{
A* a = (A*)new B; //C cast
// A* a_safe= static_cast<A*>(new B); // p.cpp:44: error: invalid static_cast from type `B*' to type `A*'
//      a_safe = static_cast<A*>(new AA); //OK !!
a->a();
a->b();
}

/* el programa ejecutando:
C:\temp>a
B::b
B::a

gcc version 3.3.1 (mingw special 20030804-1)
*/


Título: Problemilla Con Función Virtual.
Publicado por: DraKKaR en 11 de Agosto de 2004, 11:46:28 AM
 Vale, ya he pillado el fallo. Synchreowirhgoer tenía algo de razón. Habia cambiado una clase (Camera) de mi motor y lo había recompilado todo. Pero se me había olvidado recompilar el renderer (una DLL aparte que tb usa las mismas cabeceras), por lo tanto la estructura de la clase Camera era diferente para el DLL del motor que para el DLL del renderer. Recompilando el renderer funciona todo bien. :P

Ethernet, yo uso casts de C a saco del tipo:

A *a=(A*)b;


No sabía que feran malos. Voy a buscar info sobre eso del casting de C++ a ver que encuentro.

Gracias a todos por interesaros.
Título: Problemilla Con Función Virtual.
Publicado por: DraKKaR en 11 de Agosto de 2004, 12:29:50 PM
 He estado mirando algunos tutoriales. A ver si lo he entendido bien:

reinterpret_cast: este es básicamente un conversor de todo a todo (como el de C).
static_cast: conversión entre clases emparentadas (herencia) hacia arriba o hacia abajo. No comprueba que el objeto resultatte sea un objeto completo. Y puede petar.
dynamic_cast: el más completo. Como static_cast salvo que además comprueba que el objeto resultaante sea un objeto completo y válido. Añade un overhead.
const_class: kita el flag const de un puntero.
typeid: permite devolver el tipo de un objeto.

Mis dudas son:
- ¿El overhead que añade el dynamic_cast puede decrementar mucho el rendimiento? (respecto a un static_cast).
- ¿typeid devuelve el tipo de un objeto y permite comparar tipos? Creia que esto no se podia en C++. Creia que solo se hacía con lo del RTTI y que lo hacía horriblemente lento todo. ¿Tiene algo que ver con el RTTI?.
Título: Problemilla Con Función Virtual.
Publicado por: ethernet en 11 de Agosto de 2004, 01:06:40 PM
 El cast que normalmente usamos en C, debemos cambiarlo por static_cast y reinterpert_cast entre punteros siempre que sepamos que estamos haciendo, por ejemplo cuando tenemos un void* y _sabemos_ que es un puntero a una clase (se suele usar a veces con API's programadas en C).

dudo que static_cast sirva para "subir" en la herencia. Para "bajar" no es necesario cast XD

Para usar typeid y dinamic_cast debes terner activado el rtti
el dinamic_cast es para pasar e una clase Base a una heredada:

class a{};
class b :public a{},

a *ptr = new B;
b* ptr = dinamic_cast(ptr);