c++ - funciones - polimorfismo
¿Deben implementarse TODAS las funciones virtuales en las clases derivadas? (5)
El estándar ISO C ++ especifica que deben definirse todos los métodos virtuales de una clase que no son puros virtuales.
Simplemente ponga la regla es:
Si su clase derivada excede el método virtual de la clase Base, entonces debería proporcionar también una definición. De lo contrario, la clase Base debería proporcionar la definición de ese método.
Según la regla anterior en su ejemplo de código, virtual void bar();
necesita una definición en la clase Base.
Referencia:
Estándar C ++ 03: 10.3 Funciones virtuales [class.virtual]
Una función virtual declarada en una clase debe ser definida, o declarada pura (10.4) en esa clase, o ambas; pero no se requiere diagnóstico (3.2).
Entonces, debe hacer que la función sea puramente virtual o proporcionarle una definición.
El gcc faq lo documenta también:
El estándar ISO C ++ especifica que todos los métodos virtuales de una clase que no son puros virtuales deben definirse, pero no requiere ningún diagnóstico para violaciones de esta regla
[class.virtual]/8
. En función de esta suposición, GCC solo emitirá los constructores definidos implícitamente, el operador de asignación, el destructor y la tabla virtual de una clase en la unidad de traducción que define su primer método no en línea.Por lo tanto, si no define este método particular, el vinculador puede quejarse de la falta de definiciones para símbolos aparentemente no relacionados. Desafortunadamente, para mejorar este mensaje de error, puede ser necesario cambiar el enlazador, y esto no siempre se puede hacer.
La solución es garantizar que todos los métodos virtuales que no son puros estén definidos. Tenga en cuenta que se debe definir un destructor incluso si se declara pure-virtual
[class.dtor]/7
.
Esto puede parecer una pregunta simple, pero no puedo encontrar la respuesta en ningún otro lado.
Supongamos que tengo lo siguiente:
class Abstract {
public:
virtual void foo() = 0;
virtual void bar();
}
class Derived : Abstract {
public:
virtual void foo();
}
¿Está bien que la clase derivada no implemente la función bar ()? ¿Qué sucede si no TODAS mis clases derivadas necesitan la función bar (), pero algunas sí lo hacen? ¿Deben implementarse todas las funciones virtuales de una clase base abstracta en las clases derivadas, o simplemente las que son puramente virtuales? Gracias
Las clases derivadas no tienen que implementar todas las funciones virtuales. Solo necesitan implementar los puros . 1 Eso significa que la clase Derived
en la pregunta es correcta. Hereda la implementación de bar
de su clase antecesora, Abstract
. (Esto asume que Abstract::bar
está implementado en alguna parte. El código en la pregunta declara el método, pero no lo define. Puede definirlo en línea como muestra la respuesta de Trenki , o puede definirlo por separado).
1 Y aun así, solo si la clase derivada será instanciada . Si una clase derivada no se crea una instancia directamente, sino que solo existe como una clase base de más clases derivadas, entonces son esas clases las responsables de implementar todos sus métodos virtuales puros. La clase "intermedia" en la jerarquía puede dejar sin implementar algunos métodos virtuales puros, al igual que la clase base. Si la clase "intermedia" implementa un método virtual puro, sus descendientes heredarán esa implementación, por lo que no tendrán que volver a implementarla ellos mismos.
Sí, es correcto que una clase derivada tiene que OVERRIDE la función que es Pure Virtual en la clase para padres. La clase para padres que tiene una función virtual pura se llama clase abstracta solo porque su clase infantil debe dar su propio cuerpo de la función virtual pura.
Para las funciones virtuales normales: - No es necesario anularlas más, ya que algunas clases infantiles pueden tener esa función, algunas pueden no tener.
El principal objetivo del mecanismo de función virtual es el polimorfismo de tiempo de ejecución, ya sea que el objetivo principal de la función virtual pura (clase abstracta) sea hacer que sea obligatorio tener el mismo nombre Función con el propio cuerpo.
Sí, está bien ... solo necesita implementar funciones virtuales puras para instanciar una clase derivada de una clase base abstracta.
Solo los métodos virtuales puros deben implementarse en clases derivadas, pero aún necesita una definición (y no solo una declaración) de los otros métodos virtuales. Si no proporciona uno, el vinculador podría muy bien quejarse.
Entonces, solo poner {}
después de su método virtual opcional le da una implementación predeterminada vacía:
class Abstract {
public:
virtual void foo() = 0; // pure virtual must be overridden
virtual void bar() {} // virtual with empty default implementation
};
class Derived : Abstract {
public:
virtual void foo();
};
Sin embargo, una implementación predeterminada más complicada entraría en un archivo fuente separado.