Com a definição de estrutura dada abaixo ...
struct A {
virtual void hello() = 0;
};
Abordagem # 1:
struct B : public A {
virtual void hello() { ... }
};
Abordagem # 2:
struct B : public A {
void hello() { ... }
};
Existe alguma diferença entre essas duas maneiras de substituir a função hello?
c++
overriding
virtual-functions
Anarki
fonte
fonte
Respostas:
Eles são exatamente os mesmos. Não há diferença entre eles, a não ser que a primeira abordagem exija mais digitação e seja potencialmente mais clara.
fonte
override
palavra - chave.A 'virtualidade' de uma função é propagada implicitamente; no entanto, pelo menos um compilador que eu uso gera um aviso se a
virtual
palavra-chave não for usada explicitamente; portanto, convém usá-la apenas para manter o compilador quieto.De um ponto de vista puramente estilístico, a inclusão da
virtual
palavra - chave claramente 'anuncia' o fato ao usuário de que a função é virtual. Isso será importante para qualquer outra subclasse B sem ter que verificar a definição de A. Para hierarquias profundas de classe, isso se torna especialmente importante.fonte
A
virtual
palavra-chave não é necessária na classe derivada. Aqui está a documentação de suporte, do C ++ Draft Standard (N3337) (ênfase minha):fonte
Não, a
virtual
palavra-chave nas substituições de funções virtuais das classes derivadas não é necessária. Mas vale a pena mencionar uma armadilha relacionada: uma falha em substituir uma função virtual.A falha na substituição ocorre se você pretende substituir uma função virtual em uma classe derivada, mas comete um erro na assinatura para que ela declare uma função virtual nova e diferente. Essa função pode ser uma sobrecarga da função de classe base ou pode ter um nome diferente. Independentemente de você usar ou não a
virtual
palavra - chave na declaração da função de classe derivada, o compilador não poderá dizer que você deseja substituir uma função de uma classe base.Esta armadilha é, no entanto, felizmente resolvida pelo recurso de linguagem de substituição explícita do C ++ 11 , que permite ao código fonte especificar claramente que uma função de membro se destina a substituir uma função de classe base:
O compilador emitirá um erro em tempo de compilação e o erro de programação será imediatamente óbvio (talvez a função em Derivado deva ter tomado a
float
como argumento).Consulte WP: C ++ 11 .
fonte
Adicionar a palavra-chave "virtual" é uma boa prática, pois melhora a legibilidade, mas não é necessário. As funções declaradas virtuais na classe base e com a mesma assinatura nas classes derivadas são consideradas "virtuais" por padrão.
fonte
Não há diferença para o compilador, quando você escreve o
virtual
na classe derivada ou o omite.Mas você precisa olhar para a classe base para obter essas informações. Portanto, eu recomendaria adicionar a
virtual
palavra - chave também na classe derivada, se você quiser mostrar ao ser humano que essa função é virtual.fonte
Há uma diferença considerável quando você tem modelos e começa a tomar as classes base como parâmetro (s) do modelo:
A parte divertida disso é que agora você pode definir funções de interface e não interface posteriormente para definir classes. Isso é útil para interfaces de trabalho entre bibliotecas (não confie nisso como um processo de design padrão de uma única biblioteca). Não custa nada permitir isso para todas as suas aulas - você pode até
typedef
usar B se quiser.Observe que, se você fizer isso, também poderá declarar copiar / mover construtores como modelos: permitir construir a partir de interfaces diferentes permite 'transmitir' entre diferentes
B<>
tipos .É questionável se você deve adicionar suporte para o
const A&
int_hello()
. O motivo usual para essa reescrita é deixar a especialização baseada em herança para a baseada em modelo, principalmente por razões de desempenho. Se você continuar suportando a interface antiga, dificilmente poderá detectar (ou impedir) o uso antigo.fonte
A
virtual
palavra-chave deve ser adicionada às funções de uma classe base para torná-las substituíveis. No seu exemplo,struct A
é a classe base.virtual
não significa nada para usar essas funções em uma classe derivada. No entanto, se você deseja que sua classe derivada também seja uma classe base, e deseja que essa função seja substituível, será necessário colocá-lavirtual
lá.Aqui
C
herda deB
, portanto,B
não é a classe base (também é uma classe derivada) eC
é a classe derivada. O diagrama de herança é assim:Portanto, você deve colocar as
virtual
funções na frente das possíveis classes base que podem ter filhos.virtual
permite que seus filhos substituam suas funções. Não há nada errado em colocar ovirtual
funções na frente das classes derivadas, mas isso não é obrigatório. No entanto, é recomendável, porque se alguém quiser herdar da classe derivada, não ficará satisfeito com o fato de a substituição do método não funcionar conforme o esperado.Portanto, coloque-se
virtual
à frente das funções em todas as classes envolvidas na herança, a menos que você tenha certeza de que a classe não terá filhos que precisem substituir as funções da classe base. É uma boa prática.fonte
Certamente incluirei a palavra-chave Virtual para a classe filho, porque
fonte