2009-02-25 13 views
7

The CRTP se sugiere en esta pregunta sobre el polimorfismo dinámico. Sin embargo, este patrón supuestamente solo es útil para el polimorfismo estático. El diseño que estoy viendo parece verse obstaculizado por las llamadas a funciones virtuales, como hinted at here.. Una aceleración de hasta 2.5x sería fantástico.¿Hay alternativas al polimorfismo en C++?

Las clases en cuestión son simples y se pueden codificar completamente en línea, sin embargo, no se sabe hasta el momento de ejecución qué clases se utilizarán. Además, pueden estar encadenados, en cualquier orden, acumulando insultos de rendimiento en lesiones.

Cualquier sugerencia (incluso cómo se puede utilizar el CRTP en este caso) bienvenido.

Editar: Google hace una mención a las plantillas de funciones. Estos parecen prometedores.

Respuesta

3

Estoy de acuerdo con m-sharp en que no va a evitar el polimorfismo de tiempo de ejecución.

Si el valor de la optimización sobre la elegancia, intente reemplazar digamos

void invoke_trivial_on_all(const std::vector<Base*>& v) 
{ 
    for (int i=0;i<v.size();i++) 
    v[i]->trivial_virtual_method(); 
} 

con algo como

void invoke_trivial_on_all(const std::vector<Base*>& v) 
{ 
    for (int i=0;i<v.size();i++) 
    { 
    if (v[i]->tag==FooTag) 
     static_cast<Foo*>(v[i])->Foo::trivial_virtual_method(); 
    else if (v[i]->tag==BarTag) 
     static_cast<Bar*>(v[i])->Bar::trivial_virtual_method(); 
    else... 
    } 
} 

no es bastante, ciertamente no programación orientada a objetos (más una vuelta a lo que podría hacer en la vieja 'C') pero si los métodos virtuales son lo suficientemente triviales, debería obtener una función sin llamadas (sujeto a las suficientes opciones de optimización del compilador &).Una variante que use dynamic_cast o typeid podría ser un poco más elegante/segura, pero tenga en cuenta que esas características tienen sus propios gastos generales que, de todos modos, es comparable a una llamada virtual.

Dónde muy probable que vea una mejora de lo anterior es que si algunos métodos de clases hay-ops, y se salvaron de llamarlos, o si las funciones contienen código de lazo invariante común y el optimizador se las arregla para izar fuera del circuito.

+1

Creo que las declaraciones if en una plantilla pueden hacer que este lío sea un poco más limpio. Se ve prometedor de todos modos. – casualcoder

+0

POR FAVOR use static_cast <> en lugar de reinterpret_cast <>, este último dará resultados incorrectos en ciertos casos (en una implementación típica, un ejemplo sería si Foo o Bar tiene múltiples clases base y Base no es el primero entre ellos). –

+0

Buen punto gracias; respuesta actualizada – timday

18

El polimorfismo literalmente significa múltiples (poli) formas (morfos). En los lenguajes de tipo estático (como C++) hay tres tipos de polimorfismo.

  1. Polimorfismo Adhoc: Esto se ve mejor en C++ como función y método de sobrecarga. El mismo nombre de función se vinculará a diferentes métodos basados ​​en la coincidencia del tipo de tiempo de compilación de los parámetros de la llamada a la función o firma de método.
  2. Polimorfismo paramétrico: en C++ se trata de plantillas y todas las cosas divertidas que se pueden hacer, como CRTP, especialización, especialización parcial, metaprogramación, etc. De nuevo, este tipo de polimorfismo donde el mismo nombre de plantilla puede hacer diferentes cosas basadas en los parámetros de la plantilla es tiempo de compilación polimorfismo.
  3. Subtipo Polimorfismo: Finalmente, esto es lo que pensamos cuando escuchamos la palabra polimorfismo en C++. Aquí es donde las clases derivadas anulan las funciones virtuales para especializar el comportamiento. El mismo tipo de puntero a una clase base puede tener un comportamiento diferente en función del tipo derivado concreto al que apunta. Esta es la manera de obtener tiempo de ejecución polimorfismo en C++.

Si no se sabe hasta el tiempo de ejecución que se utilizarán las clases, debe utilizar Subtipo polimorfismo que implicará llamadas a funciones virtuales.

Las llamadas a métodos virtuales tienen una sobrecarga de rendimiento muy pequeña sobre las llamadas enlazadas estáticamente. Le insto a que mire las respuestas a este SO question.

-1

Puede ir a la ruta Ole C y utilizar uniones. Aunque eso también puede ser complicado.

+1

He leído esto tres veces por separado como 'cebollas' y solo pude imaginarme en qué consistía su flujo de trabajo 'desordenado'. –