Me salta un método virtual en una llamada (como si fuera una precondición de otro lenguaje)

10 views
Skip to first unread message

RFOG

unread,
Mar 2, 2018, 8:44:54 AM3/2/18
to cp...@googlegroups.com
Buenassssss.

A ver, tengo un Poltergeist del quince.

template<typename T>
class SInputCardCreator310Envelope :
public T
{...};

class SInputOutputCardCreator310Envelope :public SInputCardCreator310Envelope<SInputOutputCardDevice>
{...};

class SInputOutputCardDevice : public SInputOutputDevice
{...}; //Una jerarquía más o menos larga

template<typename T>
SInputCardCreator310Envelope<T>::SInputCardCreator310Envelope() : T(),
m_cardReader(std::make_unique<Creator310CardReader>())
{
}

class Creator310CardReader : public Creator310SmartCardReader
{...}; //Otra jerarquía más o menos compleja.

Yo, a partir de un puntero global de  SInputOutputCardCreator310Envelope, g_InputOutputCardDevice , hago un cast a 
Creator310CardReader , que es el objeto que yo quiero y deseo:

m_cardReader = reinterpret_cast<Creator310SmartCardReader*>(g_InputOutputCardDevice);

Si llamo a un método de  m_cardReader que no reciba parámetros, funciona, si llamo a un método al que le tengo que pasar algún parámetro, me salta un método de la clase base  SInputOutputDevice...

Y estoy loco porque en ensamblador, el call <address> es el call al address del método que quiero, no al de la clase base de la otra jerarquía. Además, es un método que está ahí y que no tiene nada que ver con lo que estoy haciendo.

La idea de esto es tener por un lado una clase moderna y chachi pirulis para trabajar con mi nuevo código, y luego dejar como está el "Envelope" para que trabaje con el código viejo. De hecho, el "Envelope" mapea las llamadas viejas de  SInputOutputCardDevice a las nuevas de  Creator310CardReader...

Y aquí estoy, saltándome una llamada a método que no sé de dónde me viene...

¿Alguna idea?

El código completo no os lo puedo pegar porque son unos 4.5M de líneas y luego mi jefe me mataría (a mi y a vosotros) :-)



dgutson .

unread,
Mar 2, 2018, 8:48:20 AM3/2/18
to cppba
(tl;dr) Por empezar, que tal si pones esto de una manera mas parseable, ejemplo pastebin? :)

Por otro lado, por que tenes que castear usando reinterpret_cast?

no veo ningun virtual ni herencia multiple.

--
--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
---
Has recibido este mensaje porque estás suscrito al grupo "CyC++ Buenos Aires" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+unsubscribe@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?

RFOG

unread,
Mar 2, 2018, 8:49:00 AM3/2/18
to cp...@googlegroups.com
Antes lo envío, antes me doy cuenta del asunto.

El reinterpret_cast me está reinterpretando el puntero. La llamada a la vtable es la llamada del método foráneo... porque ha coincidido. Podria haber coincidido cualquier método de cualquer clase de la jerarquía.

RFOG

unread,
Mar 2, 2018, 8:49:51 AM3/2/18
to cp...@googlegroups.com
Ya me di cuenta. Estoy usando la VTABLE de un objeto como si fuera el del otro.

RFOG

unread,
Mar 2, 2018, 8:54:57 AM3/2/18
to cp...@googlegroups.com
El reinterpret_cast es lo que me dijo ReSharper, pero si hago un dynamic_cast recibo un nulo, así que lo tengo que hacer de otra forma.

Tengo el fin de semana para pensarlo.

dgutson .

unread,
Mar 2, 2018, 9:02:57 AM3/2/18
to cppba
No entendi nada y no tengo el tiempo para entenderlo con la escasa info que das, bits que gotean de tu cabeza :)

Si necesitas ayuda, con todo gusto, pero ponele mas huevos en la explicacion y el ejemplo con highlighting o cuanto menos un poco indentado.

Jorge Atala

unread,
Mar 2, 2018, 9:41:58 AM3/2/18
to cppba
no veo la relacion entre un Creator310SmartCardReader y un SInputOutputCardCreator310Envelope, como vos bien decis, el reinterpret_cast sobre dos clases con vtables te puede dar cualquier cosa

Rafael Ontivero

unread,
Mar 2, 2018, 10:19:11 AM3/2/18
to cp...@googlegroups.com
Es que el problema era ese: que no había ninguna relación entre una cosa y la otra. Lo que el objeto hace es contener dos objetos, uno que tiene la interfaz para que el código antiguo funcione.

Luego contiene un puntero al código real, que es Creator310SmartCardReader, y es que que realmente realiza el trabajo. Lo explico mejor en la respuesta a Daniel.

Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+un...@googlegroups.com.

Rafael Ontivero

unread,
Mar 2, 2018, 10:25:41 AM3/2/18
to cp...@googlegroups.com
Ya está solucionado. No te pongo código de ejemplo porque yo también ando escaso de tiempo.

Tengo una clase A, que es la que el código obsoleto utiliza. Pero yo estoy renovando el código poco a poco con código más moderno, por lo que tengo mi clase B que es la moderna.

En este caso, declaro un hijo de A, C, que tiene toda la interfaz de A, pero que en lugar de contener un objeto de A, agrega, mediante la plantilla, un objeto de B. 

Algo así:

Class C:public A
{
Private:
 B *m_b;
};

El código resuelto de la plantilla termina en lo de arriba, evidentemente un poco más moderno con un unique_ptr y demás. Todas las llamadas de C terminan llamando a las equivalentes de B, de modo que no tengo que tocar el código antiguo.

Vale, lo que yo quería obtener es m_b a partir de la clase C, pero C no es B, sino que *contiene* a B.

Si hago un reinterpret_cast simplemente reinterpreto C como si fuera B, que no lo es, y la lío gorda con la VTABLE.

Lo que he hecho ahora, es que C me devuelve un shared_pointer a m_b, y he cambiando m_b a shared_pointer

Y ya está. Para el nuevo código obtengo m_b y para el viejo sigo con la instancia de C… hasta que la elimine en un futuro (por desgracia, lejano).

Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+un...@googlegroups.com.

dgutson .

unread,
Mar 2, 2018, 12:11:45 PM3/2/18
to cppba
Cada vez que aparece un reinterpret_cast, hay olor a culo. Es como decir givenchy o carolina herrera, pero reinterpret_cast con con aroma culo intenso.
Las unicas razones que necesite usar reinterpret_cast, es en *algunos* casos en que se interactua con codigo de C.

Rafael Ontivero

unread,
Mar 2, 2018, 1:04:25 PM3/2/18
to cp...@googlegroups.com
Ja ja. Yo el dynamic lo puse porque me lo ofreció ReSharper, pero creo que es la prirmera vez que lo usaba desde que estoy en en esta empresa (que va ya parad dos años y pico).

Solo recuerdo haberlo usado una vez en un proyecto hace varios años, para convertir un array de unsigend char en un vector o algo así, no recuerdo bien.

Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+un...@googlegroups.com.

dgutson .

unread,
Mar 2, 2018, 1:13:13 PM3/2/18
to cppba
Ahora ya sé que no hay que usar esa cosa.
Reply all
Reply to author
Forward
0 new messages