No C ++, uma função é automaticamente virtual se substituir uma função virtual?

StackOverflow https://stackoverflow.com/questions/1404797

  •  05-07-2019
  •  | 
  •  

Pergunta

Eu esperaria que foo é declarado na aula D, mas não marcado virtual, então o código a seguir chamaria a implementação de foo dentro D (independentemente do tipo dinâmico de d).

D& d = ...;
d.foo();

No entanto, no programa a seguir, esse não é o caso. Alguém pode explicar isso? Um método é automaticamente virtual se substituir uma função virtual?

#include <iostream>

using namespace std;

class C {
public:
        virtual void foo() { cout << "C" << endl; }
};

class D : public C {
public:
        void foo() { cout << "D" << endl; }
};

class E : public D {
public:
        void foo() { cout << "E" << endl; }
};

int main(int argc, char **argv)
{
        E& e = *new E;
        D& d = *static_cast<D*>(&e);
        d.foo();
        return 0;
}

A saída do programa acima é:

E
Foi útil?

Solução

Padrão 10.3.2 (Class.virtual) diz:

Se uma função de membro virtual VF for declarada em uma base de classe e em uma classe derivada, derivada direta ou indiretamente da base, uma função de membro VF com o mesmo nome e a mesma lista de parâmetros que a base :: vf é declarada, depois derivado :: vf também é virtual (seja ou não tão declarado) e substitui*

Nota de rodapé: uma função com o mesmo nome, mas uma lista de parâmetros diferente (cláusula acima), pois uma função virtual não é necessariamente virtual e não substitui. O uso do especificador virtual na declaração de uma função primordial é legal, mas redundante (possui semântica vazia). Controle de acesso (cláusula classe.access) não é considerado para determinar a substituição. --- END FOONOTE

Outras dicas

Resposta rápida pode ser não, mas a resposta correta é sim

O C ++ não conhece o esconderijo da função, portanto, substituir a função virtual sem as palavras -chave virtuais também marcam essa função virtual.

You are not creating any copy of the object of e and putting it in d. So d.foo() follows normal polymorphic behavior and calls derived class method. A method which is declared as virtual in the base class becomes automatically virtual in the derived class also.

The output ("E") behaves exactly as one would expect it to behave.

The reason: The dynamic (i.e. runtime) type of that reference is E. You are doing a static upcast to D, but that does not change the actual type of the object of course.

That's the very idea behind virtual methods and dynamic dispatches: You see the behavior of the type you were instantiating, which is E, in this case.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top