2010-06-18 12 views
26

Estoy tratando de imprimir la dirección de una función de miembro virtual. Si sé qué clase implementa la función Puedo escribir:Imprimir la dirección de la función de miembro virtual

print("address: %p", &A::func); 

Pero quiero hacer algo como esto:

A *b = new B(); 

printf("address: %p", &b->func); 
printf("address: %p", &b->A::func); 

Sin embargo, esto no se compila. ¿Es posible hacer algo como esto, tal vez buscando la dirección en el vtable en tiempo de ejecución?

Respuesta

1

No tiene mucho sentido para mí. Si usted tiene una función normal:

void f(int n) { 
} 

, entonces puede tomar su dirección:

f 

pero no se puede tomar la dirección de una función llamada, que es lo que parece querer hacer .

+0

@GMan Eso es lo que pensé que dije. De todos modos, no creo que esto sea posible. –

1

Por lo que puedo decir en el estándar, la única vez que obtiene un enlace dinámico es durante una función virtual llamada. Y una vez que ha llamado a una función, está ejecutando las instrucciones dentro de la función (es decir, no puede "detenerse a mitad de camino" en la llamada y obtener la dirección.)

Creo que es imposible.

+0

Supongo que es imposible transportable, pero conociendo la implementación debería ser posible inspeccionar la tabla virtual de un objeto en tiempo de ejecución. –

6

Los punteros a las funciones de los miembros no siempre son simples direcciones de memoria. Consulte la tabla en this article que muestra los tamaños de los punteros de funciones miembro en diferentes compiladores, algunos de hasta 20 bytes.

Como el artículo describe un puntero de función miembro, en realidad es un conjunto de datos definidos por la implementación para ayudar a resolver una llamada a través del puntero. Puede almacenarlos y llamarlos OK, pero si desea imprimirlos, ¿qué imprime? Lo mejor es tratarlo como una secuencia de bytes y obtener su longitud a través de sizeof.

+4

Sin embargo, el problema persiste: ¿cómo se identifica la función que se llama a través de una llamada 'virtual' :)? –

+1

Eso no era parte de la pregunta ¿verdad? Pero respondería 'llamándolo' :) – AshleysBrain

11

Actualmente no existe una forma estándar de hacerlo en C++, aunque la información debe estar disponible en alguna parte. De lo contrario, ¿cómo podría el programa llamar a la función? Sin embargo, GCC proporciona una extensión que nos permite recuperar la dirección de una función virtual:

void (A::*mfp)() = &A::func; 
printf("address: %p", (void*)(b->*mfp)); 

... asumiendo la función de miembro tiene el prototipo void func(). Esto puede ser muy útil cuando desea almacenar en caché la dirección de una función virtual o usarla en el código generado. GCC le advertirá sobre este constructo a menos que especifique -Wno-pmf-conversions. Es poco probable que funcione con cualquier otro compilador.

Cuestiones relacionadas