2010-08-31 7 views
7

Estoy extendiendo una clase proporcionada por una biblioteca de terceros. La clase, llamémosla Foo, tiene un método reset() que se puede invocar para reiniciar el comportamiento de Foo. El método reset() también es utilizado internamente por la clase.Exigir la virtualidad de los métodos de terceros

class Foo 
{ 
    public: 
    void reset() { 
     /* ... */ 
    } 
    void something() { 
     reset(); 
    } 
}; 

Hasta ahora, necesito sobrecargar el método reset() con el fin de restablecer mis características adicionales, así:

class Bar : public Foo 
{ 
    public: 
    void reset() { 
     /* ...something... */ 
     Foo::reset(); 
    } 
}; 

Por desgracia, ya que el método Foo::reset() no es virtual, llamando Bar::something() consigo el Foo::reset() método llamado en lugar de Bar::reset().

¿Hay alguna manera (diferente de sobrecargar Foo::something() también) de volverla virtual?

+0

Por cierto, de esta forma aprendí a establecer siempre como virtual cualquier método que sea tanto público como usado internamente. – Dacav

+1

Esa es una mala decisión, google para NVI y verá una tendencia a evitar los métodos virtuales públicos. El problema al que se enfrenta es diferente: no puede extender una clase que no fue diseñada para ser extendida. –

+0

Apoyo fuertemente las interfaces no virtuales. El uso de métodos públicos 'virtuales' es similar a devolver los controles a sus partes internas -> es un No-No. –

Respuesta

5

No puede ampliar las clases que no estaban destinadas a ser ampliadas.

1

No, esto no es posible. La virtualidad de un método se decide cuando se declara el método y no puede cambiarlo más adelante en una clase base.

Permitir que lo haga sería nada menos que un desastre. Los métodos virtuales simplemente se comportan de manera diferente que los métodos no virtuales y deben tenerse en cuenta al diseñar un objeto. Con esta propuesta, debería considerar que todos mis métodos podrían comportarse de dos maneras distintas. Eso aumenta significativamente el costo de diseño de la aplicación y reduce la confiabilidad.

1

Si ni restablecer ni algo es virtual, estás jodido, y ese es el final de la historia. Si algo es virtual, puedes anularlo. Sin embargo, si estos métodos necesarios no son virtuales, entonces la clase no debe extenderse (o implementarse correctamente, si fue diseñada).

Editar:

usted podría intentar composición, por ejemplo

class Bar { 
    Foo f; 
    // foo's methods, etc, wrapped here 
    void something() { 
     f.reset(); 
     reset(); 
    } 
}; 

Pero si necesita la conversión completa e implícita, todavía está lleno.

3

No puede hacer reset() virtual en su biblioteca de tal manera que afecte la clase base sin cambiar el código de la clase base. Para empezar, el compilador no ha agregado el código de contabilidad necesario que le permite realizar llamadas virtuales al reset().

2

No hay una 'manera limpia' de hacerlo usando herencia. Virtual es una diferencia de tiempo de compilación/enlace: el uso de un método vtable para resolver en tiempo de ejecución (virtual) frente a la vinculación directa (no virtual).

Cuestiones relacionadas