Pregunta

¿Por qué, por ejemplo, no hay soporte de idioma para examinar una vtable? ¿Por qué no puedo reemplazar una función miembro con una nueva? Tengo el presentimiento de que hay formas de dar un buen uso a tales características.

¿Hay otros idiomas que me permitan hacer tales cosas?

¿Fue útil?

Solución

La razón principal es que mantener vtable como un detalle de implementación permite que cualquier implementación concreta lo optimice como mejor le parezca; Esto significa que puede, p. recorte o incluso elimine vtable por completo si puede probar que no hay llamadas virtuales para un método dado (o todos los métodos). O puede reemplazar un envío de vtable con una verificación de tipo if-else si, p. ve que solo hay unas pocas alternativas (esto puede ser ventajoso porque la predicción de bifurcación funcionará en este caso, pero no con vtables, y también porque las bifurcaciones if-else se pueden alinear). Puede reordenar los métodos en vtable de manera tal que los llamados más comúnmente vienen antes, o los que comúnmente se llaman uno tras otro llenan los espacios adyacentes en vtable para aprovechar el almacenamiento en caché. Y así sucesivamente y así sucesivamente. Por supuesto, todas esas implementaciones también harían que el diseño de vtable fuera completamente impredecible y, por lo tanto, inútil, si fuera expuesto (por las especificaciones del lenguaje) a la implementación.

Además, las vtables no son tan simples como parecen ser. Por ejemplo, los compiladores a menudo tienen que generar thunks para arreglar el puntero this para cosas tales como herencia virtual, o herencia múltiple combinada con tipos de retorno covariantes. Esto es otra vez algo que no tiene una "mejor manera". para hacerlo (por lo que diferentes compiladores lo hacen de manera diferente), y estandarizarlo efectivamente requeriría una solución en particular.

Dicho eso, "vtable switching" es una técnica potencialmente útil si se expone como una construcción de nivel superior (para que las optimizaciones aún sean posibles). Para ver un ejemplo, consulte UnrealScript, que permite definir varios estados para una clase (una predeterminada, otra named), y anula algunos métodos en los estados con nombre. Las clases derivadas pueden anular más métodos en estados existentes, o agregar sus propios estados y anularlos en ellos. Además, los estados pueden extender otros estados (por lo tanto, si un método no se anula para un estado en particular, vuelve al estado '' padre '', y así sucesivamente hasta que la cadena alcance el estado predeterminado). Para el modelado de actores (qué juegos son esencialmente) todo esto tiene mucho sentido, por eso UnrealScript lo tiene. Y el mecanismo de implementación eficiente obvio para todo esto es el cambio de vtable, con cada estado teniendo una vtable separada.

Otros consejos

Porque es un detalle de implementación del compilador. Esa implementación puede cambiar, y cualquier código que se base en ella sería, en el mejor de los casos, frágil.

C ++ es un lenguaje en el que nunca 'paga' por lo que no usa. Este tipo de soporte en tiempo de ejecución sería contrario a esa filosofía.

Hay muchos idiomas (en el extremo más dinámico del espectro) que lo admiten.

Porque no tiene que implementarse como VTable , aunque este suele ser el caso. En resumen, ¡no hay tal cosa como VTable en C ++!

JavaScript, Python y Ruby pueden hacer esto. En esos idiomas, las definiciones de clase e instancia son mutables en tiempo de ejecución. En resumen, cada objeto y tipo es un diccionario de variables miembro y métodos que se pueden examinar y actualizar.

Esto no es posible en C ++ porque requeriría poder reescribir el código binario generado, lo que puede conllevar un costo de rendimiento sustancial.

Las Vtables solo existen en ciertas circunstancias en algunos compiladores (es decir, no están especificadas en el estándar sino que son un detalle de implementación). Incluso cuando existen, solo ocurren cuando tiene funciones virtuales y necesita la indirecta para implementar el polimorfismo. Cuando esto no es necesario, se pueden optimizar, ahorrando la sobrecarga de la indirección en la llamada.

Lamentablemente (o de lo contrario, dependiendo de sus puntos de vista sobre el asunto ;-), C ++ no fue diseñado para soportar parches de mono. En algunos casos (por ejemplo, COM), la vtable es una parte de la implementación y es posible que pueda hurgar detrás de escena. Sin embargo, esto nunca sería compatible o portátil.

Creo que puedes hacer cosas así en lenguajes dinámicos como Python:

>>> class X():
...     def bar(self): print "bar"
...     
>>> x = X()
>>> x.bar()
bar
>>> def foo(x): print "foo"
... 
>>> X.bar = foo
>>> x.bar()
foo

La diferencia con un lenguaje estático como C ++ es que el intérprete busca todos los nombres en tiempo de ejecución y luego decide qué hacer.

En C ++ es probable que haya otras soluciones para " reemplazar una función miembro con otra " problema, el más simple de los cuales podría ser utilizar punteros de función:

#include <iostream>

class X;
typedef void (*foo_func)(const X&);

void foo(const X&) { std::cout << "foo\n"; }
void bar(const X&) { std::cout << "bar\n"; }

class X
{
    foo_func f;
public:
    X(): f(foo) {}
    void foobar() { f(*this); }
    void switch_function(foo_func new_foo) { f = new_foo; }
};

int main()
{
    X x;
    x.foobar();
    x.switch_function(bar);
    x.foobar();
}

(foo y bar no usan el argumento X & amp;, en este ejemplo, similar al ejemplo de Python)

Estoy trabajando en un lenguaje compilado estáticamente que expone la vtable, y créanme que es bastante cabello para exponer.

  • Cualquier cosa que puedas hacer en C ++, puedes hacerlo en C recta con un poco de grasa en el codo.
  • Cualquier programa C modesto y razonable debe compilarse en C ++.

Quizás lo que quiere es implementar sus propias vtables sin usar la función incorporada de C ++. ¡Te divertirás mucho con las funciones de puntero a miembro (ptmf)!

Tendrá problemas para encontrar un lenguaje compilado con introspección vtable porque hay poca demanda y no es fácil de implementar. Sin embargo, para los idiomas interpretados, la situación es al revés.

  

¿Hay otros idiomas disponibles?   allí que me permiten hacer tal   cosas?

Objective-C (y Objective-C ++ también) permite el reemplazo en tiempo de ejecución de métodos ya compilados. Es la mejor combinación de técnicas estáticas y dinámicas o la peor, según a quién le pregunte.

Como otros han señalado, no existe el concepto de "vtable" en el estándar C ++, ya que es solo una técnica de implementación casi universal, muy similar al cambio de nombre.

Si está buscando poder redefinir funciones sobre la marcha en un lenguaje compilado, puede estar interesado en Common Lisp. Tiene que haber otros, pero los únicos otros idiomas en los que puedo pensar tienen herencia estática y funciones o se interpretan a un alto costo en rendimiento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top