Pregunta funciones virtuales finales en C ++ 0x


Leyendo que puedes tener funciones virtuales finales en C ++ 0x estoy un poco confundido. ¿Cuál es la diferencia de simplemente omitir ambos modificadores en primer lugar?


5
2017-07-22 09:52


origen


Respuestas:


La diferencia que se produce no es la base que la usa, sino la derivada.

class Base {
    virtual void foo() = 0;
};
class Derived : Base {
    void foo() {} 
    // Still virtual because it's virtual in base- no way to "un-virtual" it

    virtual void foo() final {} 
    // Now un-overridable.
};

Piense en ello no como prevención de anulaciones, sino para evitar anulaciones "más".


10
2017-07-22 09:56



Cuando me topé con el uso de la final palabra clave junto con virtual en C ++, me preguntaba lo mismo:

Si declara un método virtual Lo hace heredable y reemplazable, y declara un método. final evita que ese método sea anulado, no declara un método ambos formar una contradiccion?

Creo que el actual respuesta aceptada a esta pregunta es bueno, pero quería basarme un poco más en lo que encontré investigando sobre esto.

Considera la siguiente clase:

class A {
    public:
        void hide_me();
        virtual void override_me();
        virtual void cant_override_me() final;
};

Lo importante es darse cuenta de que las tres declaraciones de métodos son todas distintas y significan cosas diferentes.

El primero:

    void hide_me();

es no virtual y, por lo tanto, por definición, no puede ser anulado.

El tercero:

    virtual void cant_override_me() final;

es declarado final, y por lo tanto no puede ser anulado, también por definición.

La diferencia es que desde hide_me es no virtual, anulando es inaplicable, mientras que puedes pensar en cant_override_me como elegible ser anulado (porque es virtual,) pero también tiene anulación discapacitado debido a la final modificador En otras palabras, la anulación no se aplica a los métodos que no están declarados virtual, pero se aplica a virtual métodos, simplemente no puede anularlos si también están declarados final.

Ahora considera una clase infantil:

class B: public A {
    public:
        void hide_me(); // this hide's A's definition of "hide_me()"; this is not overriding.
        void override_me(); // implicit "virtual"
        //void cant_override_me(); // implicit "virtual"; compilation fails
};

poder redefinir hide_me() para clase B, pero esto es solo sobrecargar o ocultación, de ahí el nombre de la función. B todavía puede acceder Aes hide_me método a través de A::hide_me(), pero alguien más que tiene una referencia a B declarado como B, es decir

B *my_b = new B();

debe acceder Adefinición ahora oculta de hide_me vía my_b->A::hide_me().

no poder proporcionar una redefinición de cant_override_me() en B.

Como un ejemplo completo, aquí hay una ligera redefinición del programa para ayudar a ejemplificar lo que está sucediendo:

#include <cstdio>    
class A {
    public:
        inline void hide_me() {
            printf("a hide_me\n");
        }
        virtual void override_me();
        virtual void cant_override_me() final;
};

class B: public A {
    public:
        inline void hide_me() {
            printf("b hide_me\n");
        }
        void override_me();
        inline void foo() {
            A::hide_me();
        }
        // can't override cant_override_me
};

void A::override_me() {
    printf("a override_me\n");
}

void A::cant_override_me() {
    printf("a cant_override_me\n");
}

void B::override_me() {
    printf("b override_me\n");
}

int main (int argc, char *argv[]) {
    A *a = new A();
    A *ab = new B();
    B *b = new B();

    a->hide_me();
    ab->hide_me();
    b->hide_me();
    b->A::hide_me();

    printf("---\n");

    a->override_me();
    ab->override_me();
    b->override_me();
    b->A::override_me();
}

Los resultados del programa

a hide_me
a hide_me
b hide_me
a hide_me
---
a override_me
b override_me
b override_me
a override_me

1
2017-07-01 17:23