A menudo utilizo clases virtuales puras (interfaces) para reducir las dependencias entre implementaciones de diferentes clases en mi proyecto actual. No es inusual para mí incluso tener jerarquías en las que tengo clases virtuales puras y no puras que extienden otras clases virtuales puras. Este es un ejemplo de tal situación:¿Es una buena convención heredar virtualmente de las clases virtuales puras (interfaz)?
class Engine
{ /* Declares pure virtual methods only */ }
class RunnableEngine : public virtual Engine
{ /* Defines some of the methods declared in Engine */ }
class RenderingEngine : public virtual Engine
{ /* Declares additional pure virtual methods only */ }
class SimpleOpenGLRenderingEngine : public RunnableEngine,
public virtual RenderingEngine
{ /* Defines the methods declared in Engine and RenderingEngine (that are not
already taken care of by RunnableEngine) */ }
Tanto RunnableEngine
y RenderingEngine
extienden Engine
prácticamente de manera que el problema de diamante no afecta SimpleOpenGLRenderingEngine
.
Quiero tomar una postura preventiva contra el problema del diamante en lugar de tratarlo cuando se convierte en un problema, especialmente porque me gusta escribir un código que sea tan fácil de usar como sea posible para otra persona y no quiero ellos tienen que modificar mis clases para que puedan crear jerarquías de clases particulares, por ejemplo si Bob quería hacer esto:
class BobsRenderingEngine : public virtual RenderingEngine
{ /* Declares additional pure virtual methods only */ }
class BobsOpenGLRenderingEngine : public SimpleOpenGLRenderingEngine,
public BobsRenderingEngine
{ /* Defines the methods declared in BobsRenderingEngine */ }
Esto no sería posible si no hubiera hecho SimpleOpenGLRenderingEngine
se extienden prácticamente RenderingEngine
. Soy consciente de que la probabilidad de que Bob quiera hacer esto puede ser muy baja.
Por lo tanto, he comenzado a utilizar la convención de extender siempre las clases virtuales puras virtualmente para que la herencia múltiple de ellas no cause el problema del diamante. Tal vez esto se deba a que procedo de Java y tengo tendencia a usar solo herencia individual con clases virtuales no puras. Estoy seguro de que probablemente sea excesivo en algunas situaciones, pero ¿hay algún inconveniente para usar esta convención? ¿Podría esto causar algún problema con el rendimiento/funcionalidad, etc.? Si no, no veo una razón para no usar la convención, incluso si a menudo no es necesaria al final.
Sí, completa la sobrecarga. Solo es un verdadero problema de diamantes cuando tiene múltiples * implementaciones * para elegir. No es un problema con una interfaz, no tiene ninguna implementación. La herencia virtual es una curita, solo la usas cuando tu espalda está contra la pared. –
@HansPassant, no estoy de acuerdo con usted. El problema de Dimond a menudo puede ocurrir incluso con clases virtuales puras. Supongamos que tiene una interfaz, digamos IA, y su implementación predeterminada 'AImpl: IA virtual pública', y luego usando herencia virtual puede definir una 'clase B: IA virtual pública, AImpl pública '. Por lo tanto, B usará la implementación de AImpl de IA. –
@kids_fok Sí, ahí es exactamente donde tengo el problema. Bueno, no estoy seguro de que necesites 'B' para extender' IA' explícitamente en tu ejemplo con el ejemplo en mi pregunta es similar. –