2009-03-19 10 views
8

me encontré con el siguiente código en una biblioteca:¿Cuál es la ventaja de esta llamada de función indirecta?

class Bar { 
public: 
    bool foo(int i) { 
    return foo_(i); 
    } 
private: 
    virtual bool foo_(int i) = 0; 
}; 

Ahora me pregunto: ¿Por qué utilizar esta vía indirecta? ¿Puede haber alguna razón por la anterior sería mejor que la alternativa sencilla:

class Bar { 
public: 
    virtual bool foo(int i) = 0; 
}; 

Respuesta

10

Este es el Non-Virtual Interface Idiom (NVI). Esa página de Herb Sutter tiene muchos detalles al respecto. Sin embargo, atempere lo que lee allí con lo que las preguntas frecuentes de C++ Lite dicen here y here.

La principal ventaja de NVI es separar la interfaz de la implementación. Una clase base puede implementar un algoritmo genérico y presentarlo al mundo, mientras que sus subclases pueden implementar los detalles del algoritmo a través de funciones virtuales. Los usuarios externos están protegidos de los cambios en los detalles del algoritmo, especialmente si luego decide que desea agregar un código de procesamiento previo y posterior.

La desventaja obvia es que tiene que escribir un código adicional. Además, las funciones virtuales private son confusas para mucha gente. Muchos codificadores creen erróneamente que no puedes anularlos. A Herb Sutter parece gustarle private virtuales, pero en mi humilde opinión es más efectivo en la práctica seguir las recomendaciones de C++ FAQ Lite y hacer que sean protected.

3

Esto es a menudo llamado un par Plantilla-Hook (a.k.a hotspot), acuñadas por Wolfgang Pree.

ver este PDF, PowerPoint, HTML

Una razón para hacer el indirección como usted la llama es que las cosas a menudo puede/debe ser configuración antes de un método, y algunos cleaing posterior una llamada de método En las subclases sólo tiene que suministrar el comportamiento necesario sin hacer la configuración y limpieza ...

0

Si una subclase podría cambiar la definición de loquesea _ ?, pero los consumidores necesita una función estática (para la eficiencia) ? ¿O para un patrón de delegación?

2

Este es el patrón de la plantilla. El método foo contiene código que deben ejecutar todas las subclases. Tiene más sentido cuando se mire como esto:

class Bar { 
public: 
    bool foo(int i) { 
    // Setup/initialization/error checking/input validation etc 
    // that must be done for all subclasses 
    return foo_(i); 
    } 
private: 
    virtual bool foo_(int i) = 0; 
}; 

Es mejor que la alternativa, que es tratar de recordar llamar el código común en cada subclase de forma individual. Inevitablemente, alguien hace una subclase pero olvida llamar al código común, lo que da como resultado una cantidad de problemas.

Cuestiones relacionadas