Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Problemilla Con Función Virtual.

Iniciado por DraKKaR, 10 de Agosto de 2004, 06:06:31 PM

« anterior - próximo »

DraKKaR

 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++.

Zaelsius

 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).

Haddd

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


synchrnzr

 ¿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

DraKKaR

 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)

DraKKaR

 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.

StraT

 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
quot;Solo hay dos cosas infinitas, el universo y la estupidez humana, aunque de lo primero no estoy muy seguro\\\" Einstein

Mars Attacks

 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...

ethernet

 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)
*/



DraKKaR

 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.

DraKKaR

 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?.

ethernet

 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);






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.