una sirve que programacion para metodos metodo interfaz interfaces implementacion ejemplos ejemplo clase abstractos abstracto abstracta c++ performance abstract-class virtual-functions

c++ - programacion - para que sirve una clase abstracta



¿Penalización de rendimiento por trabajar con interfaces en C++? (16)

Cuando llamas a una función virtual (por ejemplo, a través de una interfaz), el programa debe buscar la función en una tabla para ver qué función llamar para ese objeto. Esto da una pequeña penalización en comparación con una llamada directa a la función.

Además, cuando utiliza una función virtual, el compilador no puede alinear la llamada a la función. Por lo tanto, podría haber una penalización al uso de una función virtual para algunas funciones pequeñas. En general, este es el mayor "golpe" de rendimiento que es probable que veas. Esto realmente solo es un problema si la función es pequeña y se llama muchas veces, digamos desde dentro de un bucle.

¿Hay una penalización de rendimiento en tiempo de ejecución cuando se utilizan interfaces (clases base abstractas) en C ++?


El uso de clases base abstractas en C ++ generalmente exige el uso de una tabla de funciones virtuales, todas las llamadas a la interfaz se buscarán a través de esa tabla. El costo es pequeño en comparación con una llamada a función sin formato, así que asegúrese de que necesita ir más rápido que eso antes de preocuparse por ello.


En cuanto a cualquier clase que contiene una función virtual, se usa un vtable. Obviamente, invocar un método a través de un mecanismo de envío como un vtable es más lento que una llamada directa, pero en la mayoría de los casos puede vivir con eso.


Hay una pequeña penalización por llamada de función virtual en comparación con una llamada normal. Es poco probable que observe una diferencia a menos que esté haciendo cientos de miles de llamadas por segundo, y el precio a menudo vale la pena pagar por la claridad del código agregado de todos modos.


La única diferencia principal que conozco es que, dado que no estás usando una clase concreta, forrar es (¿mucho?) Más difícil de hacer.


La mayoría de las personas nota la penalización de tiempo de ejecución, y con razón.

Sin embargo, en mi experiencia trabajando en proyectos grandes, los beneficios de las interfaces claras y la encapsulación adecuada compensan rápidamente la ganancia de velocidad. El código modular se puede intercambiar para una implementación mejorada, por lo que el resultado neto es una gran ganancia.

Su kilometraje puede variar, y claramente depende de la aplicación que está desarrollando.


Lo único que se me ocurre es que los métodos virtuales son un poco más lentos para llamar que los métodos no virtuales, porque la llamada debe pasar por la tabla de métodos virtuales .

Sin embargo, esta es una mala razón para arruinar su diseño. Si necesita más rendimiento, use un servidor más rápido.


No creo que la comparación de costos se realice entre una llamada de función virtual y una llamada de función directa. Si está pensando en utilizar una clase base abstracta (interfaz), entonces tiene una situación en la que desea realizar una de varias acciones basadas en el tipo dinámico de un objeto. Tienes que tomar esa decisión de alguna manera. Una opción es usar funciones virtuales. Otro es un cambio en el tipo de objeto, ya sea a través de RTTI (potencialmente costoso), o agregando un método de tipo () a la clase base (posiblemente aumentando el uso de memoria de cada objeto). Por lo tanto, el costo de la llamada de función virtual se debe comparar con el costo de la alternativa, no con el costo de no hacer nada.


Otra alternativa que es aplicable en algunos casos es el polimorfismo en tiempo de compilación con plantillas. Es útil, por ejemplo, cuando desea realizar una elección de implementación al comienzo del programa y luego usarla durante la ejecución. Un ejemplo con polimorfismo en tiempo de ejecución

class AbstractAlgo { virtual int func(); }; class Algo1 : public AbstractAlgo { virtual int func(); }; class Algo2 : public AbstractAlgo { virtual int func(); }; void compute(AbstractAlgo* algo) { // Use algo many times, paying virtual function cost each time } int main() { int which; AbstractAlgo* algo; // read which from config file if (which == 1) algo = new Algo1(); else algo = new Algo2(); compute(algo); }

Lo mismo usando polimorfismo en tiempo de compilación

class Algo1 { int func(); }; class Algo2 { int func(); }; template<class ALGO> void compute() { ALGO algo; // Use algo many times. No virtual function cost, and func() may be inlined. } int main() { int which; // read which from config file if (which == 1) compute<Algo1>(); else compute<Algo2>(); }


Sí, hay una penalización Algo que puede mejorar el rendimiento en su plataforma es usar una clase no abstracta sin funciones virtuales. Luego use un puntero de función miembro para su función no virtual.


Sí, pero nada digno de mención, que yo sepa. El golpe de rendimiento se debe a la ''indirección'' que tienes en cada llamada al método.

Sin embargo, realmente depende del compilador que está utilizando, ya que algunos compiladores no pueden alinear las llamadas al método dentro de las clases heredadas de la clase base abstracta.

Si quiere estar seguro de que debe ejecutar sus propias pruebas.


Una cosa que debe tenerse en cuenta es que el costo de llamadas a funciones virtuales puede variar de una plataforma a otra. En las consolas, pueden ser más notorios, ya que usualmente la llamada vtable significa una falta de caché y puede atornillar la predicción de la rama.


Tenga en cuenta que la herencia múltiple abota la instancia del objeto con múltiples punteros vtable. Con G ++ en x86, si su clase tiene un método virtual y ninguna clase base, tiene un puntero a vtable. Si tiene una clase base con métodos virtuales, todavía tiene un puntero a vtable. Si tiene dos clases base con métodos virtuales, tiene dos punteros vtable en cada instancia .

Por lo tanto, con la herencia múltiple (que es lo que implementan las interfaces en C ++), usted paga clases base por tamaño de puntero en el tamaño de instancia del objeto. El aumento en la huella de memoria puede tener implicaciones indirectas de rendimiento.


Respuesta corta: No.

Respuesta larga: No es la clase base o el número de antepasados ​​que una clase tiene en su jerarquía lo que afecta su velocidad. Lo único es el costo de una llamada a un método.

Una llamada a un método no virtual tiene un costo (pero puede estar en línea)
Una llamada a un método virtual tiene un costo ligeramente más alto, ya que necesita buscar el método para llamar antes de llamarlo (pero esta es una simple búsqueda de tabla, no de búsqueda). Como todos los métodos en una interfaz son virtuales por definición, existe este costo.

A menos que esté escribiendo alguna aplicación sensible a la velocidad de hiper, esto no debería ser un problema. La claridad adicional que recibirá al usar una interfaz generalmente compensa cualquier disminución percibida de velocidad.


Sé que es un punto de vista poco común, pero incluso mencionar este tema me hace sospechar que estás pensando demasiado en la estructura de la clase. He visto muchos sistemas que tenían demasiados "niveles de abstracción", y eso solo los hacía propensos a graves problemas de rendimiento, no por el costo de las llamadas a métodos, sino por la tendencia a hacer llamadas innecesarias. Si esto sucede en múltiples niveles, es un asesino. echar un vistazo


Las funciones llamadas mediante despacho virtual no están en línea

Existe un tipo de penalización para las funciones virtuales que es fácil de olvidar: las llamadas virtuales no están en línea en una situación (común) donde no se conoce el tipo de objeto del tiempo de compilación. Si su función es pequeña y adecuada para enlining, esta penalización puede ser muy significativa, ya que no solo está agregando una sobrecarga de llamada, sino que el compilador también está limitado en cuanto a cómo puede optimizar la función de llamada (debe asumir que la función virtual puede han cambiado algunos registros o ubicaciones de memoria, no puede propagar valores constantes entre el llamante y el destinatario).

El costo de la llamada virtual depende de la plataforma

En cuanto a la penalización por sobrecarga de llamadas en comparación con una llamada de función normal, la respuesta depende de su plataforma de destino. Si su objetivo es una PC con CPU x86 / x64, la penalización para llamar a una función virtual es muy pequeña, ya que la CPU moderna x86 / x64 puede realizar la predicción de bifurcación en llamadas indirectas. Sin embargo, si tiene como objetivo un PowerPC o alguna otra plataforma RISC, la penalización de llamadas virtuales puede ser bastante significativa, ya que las llamadas indirectas nunca se predicen en algunas plataformas (Cf. PC / Xbox 360 Cross Platform Development Best Practices ).