tipos - ventajas de la herencia en c++




Uso de la herencia virtual (2)

Necesito escribir una convención de codificación que será utilizada tanto por los novatos como por los desarrolladores experimentados de C ++. La regla sobre la herencia para el polimorfismo dinámico es la siguiente:

  • Para el polimorfismo dinámico, considere el uso de herencia única (jerarquía en forma de árbol), posiblemente con herencia múltiple de interfaces abstractas
  • para la herencia a lo largo de la jerarquía (clases base, etc.), de forma predeterminada , use la herencia pública
  • para la herencia de la interfaz abstracta, de forma predeterminada , use la herencia virtual pública

A esta regla le seguirá una información detallada sobre la implementación, posibles excepciones, etc.

Entonces, la pregunta: ¿Es esta regla deseable tanto para los novatos como para los desarrolladores de C ++ con experiencia? (Pros / contras, así como fuentes y enlaces son bienvenidos)

Los que veo son:

Pros:

  • Regla fácilmente utilizable por los novatos, sin restringir a los desarrolladores experimentados.
  • familiar para aquellos que ya están familiarizados con las interfaces de Java / .NET
  • esquiva los problemas relacionados con la herencia virtual de la implementación (ya que está reservada para interfaces abstractas), así como la herencia no virtual (posible ambigüedad al realizar la conversión a la clase de interfaz)

Contras:

  • ligero costo de rendimiento (velocidad al lanzar a la interfaz, tamaño de las tablas virtuales, punteros adicionales en la instancia de clase)

Nota: He leído las siguientes fuentes en línea:

Nota 2: El uso del nombre de "interfaz abstracta" se acuñó después del uso de Sutter & Alexandrescu en el ítem 36 de "Estándares de codificación C ++"

Este es un caso que debería funcionar (su equivalente en Java / C # usando interfaces simplemente funciona), pero eso no funciona en C ++ si la herencia de la interfaz no es virtual:

class A
{
   public :
      virtual ~A() = 0 {}
} ;

class B : public A {} ; // should have been virtual to avoid the error
class C : public A {} ; // should have been virtual to avoid the error

class D : public B, public C
{
   public : 
      virtual ~D() {}
} ;

void foo(A * c) {}
void bar(D * d)
{
   foo(d) ; // Error: ambiguous conversions from 'D *' to 'A *
}

Y sí, la conversión explícita para eliminar la ambigüedad es la solución incorrecta (la conversión explícita suele ser la solución incorrecta de todos modos).


¿Sabes que? Ya das toda la información importante en la pregunta. No veo nada que responder a nivel técnico. Y al parecer, nadie más vio ningún problema técnico significativo con lo que publicaste tampoco.

Sin embargo, responderé a tu audaz pregunta: , es adecuado tanto para newbs como para profesionales.

  • Newbs tiene algunas directrices técnicas útiles.
  • Los profesionales pueden hacer lo que quieran si pueden dar una razón, porque califica sus reglas con "considerar" y "por defecto", por lo que básicamente nadie más puede decir que debe hacerlo más o menos debido a las reglas de estilo, porque sus reglas 'frases ya permiten excepciones.

El ejemplo de su herencia no funciona si no es virtual debido al clásico problema de herencia múltiple en c ++, el diamante de la muerte . Básicamente, si no especifica la herencia virtual, cada clase principal (B, C) tiene sus propios objetos A de base. Esto hace que todos los accesos a las funciones y variables no estáticas de la clase base (conversión y también suponiendo) sean ambiguos. No puedo imaginar una situación en la que puedas evitar esto en c ++.

Edición: Para el registro este es el código de trabajo:

class A
{
public :
    virtual ~A() {}
};

class B : virtual public A {};
class C : virtual public A {};

class D : virtual public B, virtual public C
{
public :
    virtual ~D() {}
};

void foo(A * c) {}
void bar(D * d)
{
    foo(d);
}

int main(void)
{
    D d;
    foo(&d);
    return 0;
}




multiple-inheritance