2009-05-07 23 views

Respuesta

7

Una función solo necesita ser virtual si una clase derivada implementará esa función de una manera diferente.

Por ejemplo:

class Base { 
public: 
    void setI (int i) // No need for it to be virtual 
    { 
    m_i = i; 
    } 

    virtual ~Base() {}   // Almost always a good idea 

    virtual bool isDerived1() // Is overridden - so make it virtual 
    { 
    return false; 
    } 

private: 
    int m_i; 
}; 

class Derived1 : public Base { 
public: 
    virtual ~Derived() {} 

    virtual bool isDerived1() // Is overridden - so make it virtual 
    { 
    return true; 
    } 
}; 

Como resultado de ello, me gustaría error del lado de no tener nada virtuales a menos que sepa de antemano que tiene la intención de anularlo o hasta que se descubre que necesita el comportamiento. La única excepción a esto es el destructor, para el cual es casi siempre el caso que desea que sea virtual en una clase base.

+1

Cuando al menos un método es virtual en una clase, debe tener el destructor virtual. – stefanB

0

Las funciones de interfaz deben ser, en general, virtuales. Las funciones que proporcionan funcionalidad fija no deberían.

2

Tiendo a hacer que solo las cosas que deseo sean anulables sean virtuales. Si mis suposiciones iniciales sobre lo que deseo anular resultan incorrectas, retrocedo y cambio la clase base.

Ah, y obviamente siempre haga que su destructor sea virtual si está trabajando en algo de lo que se heredará.

0

¿Por qué declarar algo virtual hasta que realmente lo está anulando? Creo que no se trata de estar seguro o no. Siga los hechos: ¿está anulado en alguna parte? ¿No? Entonces no debe ser virtual.

+0

Esto da como resultado una situación en la que si desea cambiar una subclase (para anular un método previamente no anulado), debe cambiar la clase base (para hacer que el método sea virtual), lo que significa que debe recompilar todos los códigos la clase base. En algunos proyectos, la fragilidad de la clase base no es un problema, pero en otros sí lo es. Depende de su proceso de compilación y de si ha publicado la interfaz de la clase base. –

+1

Por lo tanto, los métodos IMO deben ser virtuales si se permite que las subclases los anulen (y se admite el polimorfismo en tiempo de ejecución), y no si realmente lo hacen. –

1

Si va a crear una clase base (que está seguro de que alguien se deriva de la clase), entonces usted puede hacer las cosas siguientes:

  • Hacer destructor virtual (una necesidad para la clase base)
  • Definir métodos que debe ser derivado y hacerlos virtuales.
  • Defina métodos que no necesitan ser (o no deberían ser) derivados como no virtuales.
  • Si las funciones son solo para la clase derivada y no para la clase base, marque como protegidas.
1

El compilador no sabría qué parte real de código se ejecutará cuando el puntero de tipo base llame a una función virtual. por lo tanto, la pieza real de código que se ejecutará debe evaluarse en tiempo de ejecución de acuerdo con el objeto apuntado por el puntero de la clase base. Por lo tanto, evite el uso de la función virtual si la función no debe ser anulada en una clase heredada.

Versión TLDR: "debe tener un conjunto de funciones virtuales y un conjunto de funciones no virtuales de las que está seguro no van a heredarse". Porque las funciones virtuales provocan una disminución del rendimiento en el tiempo de ejecución.

4

Solo debe hacer que las funciones que pretende y diseñar sean reemplazadas de forma virtual. Hacer un método virtual no es gratuito en términos de mantenimiento y rendimiento (el mantenimiento es el problema mucho más grande en mi humilde opinión).

Una vez que un método es virtual, se vuelve más difícil razonar sobre cualquier código que use este método.Porque en lugar de considerar lo que haría una llamada a un método, debe considerar lo que las llamadas a los métodos N harían en ese escenario. N representa el número de sub clases que anulan ese método.

La única excepción a esta regla son los destructores. Deben ser virtuales en cualquier clase de la que se pretenda derivar. Es la única manera de garantizar que se llame al destructor apropiado durante la desasignación.

4

El idioma de interfaz no virtual (C++ Coding Standards elemento 39) dice que una clase base debe tener métodos de interfaz no virtuales, permitiendo que la clase base garantice invariantes y métodos virtuales no públicos para la personalización de la clase base comportamiento por clases derivadas. Los métodos de interfaz no virtual llaman a los métodos virtuales para proporcionar el comportamiento sobresatible.

+0

Considera agregar la fuente aquí. Encontrado se refiere a "Estándares de codificación de C++, 101 reglas, pautas y mejores prácticas, Herb Sutter y Andrej Alexandrescu". Sin embargo, no existe un estándar de codificación oficial en C++. – patrik

Cuestiones relacionadas