Requerir invalidaciones de funciones virtuales para usar la palabra clave override


C++11 agregó override para asegurarse de que las funciones miembro que escribe que tiene la intención de anular las funciones virtuales de clase base realmente lo hacen (o no compilarán).

Pero en una jerarquía de objetos grande, a veces podría terminar accidentalmente escribiendo una función miembro que anula una clase base virtual cuando no lo pretendía. Por ejemplo:

struct A {
    virtual void foo() { }  // because obviously every class has foo().
};

struct B : A { ... };

class C : B {
private:
    void foo() {
        // was intended to be a private function local to C
        // not intended to override A::foo(), but now does
    }
};

¿Hay algún indicador/extensión del compilador que al menos emita una advertencia en C::foo? Por legibilidad y corrección, me gustaría para forzar que todas las anulaciones usen override.

Author: Barry, 2015-03-19

4 answers

Parece que la versión 5.1 de GCC agregó exactamente la advertencia que estaba buscando:

-Wsuggest-override
       Advertir sobre la sobreescritura de funciones virtuales que no están marcadas con la palabra clave sobreescritura.

Compilando con -Wsuggest-override -Werror=suggest-override entonces obligaría a que todas las anulaciones usen override.

 26
Author: Barry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-26 14:38:05

Hay dos cosas que puedes hacer.

Primero, Clang 3.5 y superior tienen una advertencia -Winconsistent-missing-override (activada por -Wall). Esto no funciona para su ejemplo, pero solo si agrega un void foo() override {} a class B y no en class C. Lo que realmente quieres es -Wmissing-override, localizar todos los override que faltan, no solo los que faltan inconsistentemente. Eso no se proporciona actualmente, pero es posible que se queje en la lista de correo Clang y pueden agregarlo.

En segundo lugar, se utiliza Howard Hinnant's truco para temporalmente agregue final a la función miembro de la clase base y recompile. El compilador localizará entonces todas las clases derivadas que intenten sobreescribir la función miembro base virtual. A continuación, puede arreglar los que faltan. Es un poco más de trabajo y requiere una revisión frecuente cuando su jerarquía de clases se expande.

 11
Author: TemplateRex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:07

El problema que veo con -Werror=suggest-override es que no te permite escribir lo siguiente:

void f() final {...}

Aunque hay un override implícito aquí. El -Werror=suggest-override no ignora esto (como debería, ya que el override es redundante en este caso)

, Pero es más complicado que eso... Si escribe

virtual void f() final {...}

Significa una cosa completamente diferente de

virtual void f() override final {...}

¡El primer caso no necesita anular nada! El segundo sí.

Así que estoy asumiendo el cheque GCC se implementa de esta manera (es decir, a veces aceptar el redundante override) con el fin de obtener el último caso correcto. Pero esto no funciona bien, por ejemplo, con clang-tidy, que eliminará correctamente la anulación cuando final sea suficiente (pero entonces la compilación de GCC fallará...)

 3
Author: user46317,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-23 17:24:53

GCC y Clang están cubiertos por otras respuestas. Aquí está lo mismo para VC++ de mi otra respuesta :

A continuación se muestran los números de advertencia relevantes en VC++:

C4263 (level 4) 'function': member function does not override any base class virtual member function
C4266 (level 4) 'function': no override available for virtual member function from base 'type'; function is hidden

Para habilitar estas dos advertencias, puede usar una de las siguientes opciones:

  1. Establezca el nivel de advertencia en 4 en la configuración del proyecto y luego deshabilite las advertencias que no desee. Esta es mi forma preferida. Para deshabilitar las advertencias de nivel 4 no deseadas, vaya a configuración del proyecto > C / C++ > Avanzado y luego ingrese los números de advertencia en Desactive el cuadro de Advertencias Específicas.
  2. Habilite las dos advertencias anteriores utilizando el código.

    #pragma warning(default:4263)
    #pragma warning(default:4266)
    
  3. Habilite las dos advertencias anteriores en configuración del proyecto > C / C++ > Línea de comandos y luego ingrese /w34263 / w34266. Aquí la opción / wNxxxx significa habilitar las advertencias xxxx en el nivel N (N = 3 es el nivel predeterminado). También puede hacer /wdNxxxx que desactiva la advertencia xxxx en el nivel N.

 -1
Author: ShitalShah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:26