Eu tenho uma classe base com uma função virtual e quero substituir essa função em uma classe derivada. Existe alguma maneira de fazer o compilador verificar se a função que declarei na classe derivada realmente substitui uma função na classe base? Gostaria de adicionar alguma macro ou algo que garanta que eu não declarei acidentalmente uma nova função, em vez de substituir a antiga.
Veja este exemplo:
class parent {
public:
virtual void handle_event(int something) const {
// boring default code
}
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
Aqui parent::handle_event()
é chamado em vez de child::handle_event()
, porque o método da criança perde a const
declaração e, portanto, declara um novo método. Isso também pode ser um erro de digitação no nome da função ou alguma pequena diferença nos tipos de parâmetros. Também pode acontecer facilmente se a interface da classe base mudar e em algum lugar alguma classe derivada não foi atualizada para refletir a mudança.
Existe alguma maneira de evitar esse problema, posso de alguma forma dizer ao compilador ou alguma outra ferramenta para verificar isso para mim? Quaisquer sinalizadores de compilador úteis (de preferência para g ++)? Como você evita esses problemas?
Respostas:
Desde o g ++ 4.7, ele entende a nova
override
palavra-chave C ++ 11 :fonte
override
deve ser usado na definição. Uma implementação inline é tanto definição quanto implementação, então tudo bem.Algo como a
override
palavra-chave do C # não faz parte do C ++.No gcc,
-Woverloaded-virtual
adverte contra ocultar uma função virtual da classe base com uma função de mesmo nome, mas uma assinatura suficientemente diferente para que não a substitua. No entanto, isso não o protegerá contra a falha em substituir uma função devido à grafia incorreta do próprio nome da função.fonte
override
uma palavra-chave em C ++; isso pode significar que você está usando algo que pode compilar algum código-fonte C ++ inválido. ;)override
funcionalidade do estilo C # ; Raramente tive problemas com substituições com falha e eles são relativamente fáceis de diagnosticar e consertar. Uma coisa com a qual não concordo é que os usuários de VC ++ devem usá-lo. Eu prefiro que o C ++ se pareça com o C ++ em todas as plataformas, mesmo que um projeto específico não precise ser portátil. É importante notar que C ++ 0x terá atributos e[[base_check]]
, portanto, você pode optar por ignorar a verificação, se desejar.[[override]]
[[hiding]]
override
uma palavra - chave , parece que sim . Bem, não é uma palavra-chave adequada, mas um identificador especial em C ++ 11. A Microsoft se esforçou o suficiente para fazer disso um caso especial e seguir o formato geral para atributos eoverride
torná-lo padrão :)Pelo que eu sei, você não pode simplesmente torná-lo abstrato?
Pensei ter lido em www.parashift.com que você pode realmente implementar um método abstrato. O que faz sentido para mim pessoalmente, a única coisa que faz é forçar as subclasses a implementá-lo, ninguém disse nada sobre não ser permitido ter uma implementação em si.
fonte
BaseClass::method()
) seja chamado na implementação derivada (digamosDerivedClass::method()
), por exemplo, para um valor padrão.No MSVC, você pode usar a
override
palavra-chave CLR mesmo se não estiver compilando para CLR.No g ++, não há uma maneira direta de impor isso em todos os casos; outras pessoas deram boas respostas sobre como detectar diferenças de assinatura usando
-Woverloaded-virtual
. Em uma versão futura, alguém pode adicionar sintaxe como__attribute__ ((override))
ou equivalente usando a sintaxe C ++ 0x.fonte
Em MSVC ++ você pode usar palavras-chave
override
override
funciona tanto para código nativo quanto para código CLR em MSVC ++.fonte
Torne a função abstrata, de forma que as classes derivadas não tenham outra escolha a não ser substituí-la.
@Ray Seu código é inválido.
Funções abstratas não podem ter corpos definidos em linha. Deve ser modificado para se tornar
fonte
Eu sugeriria uma pequena mudança em sua lógica. Pode ou não funcionar, dependendo do que você precisa realizar.
handle_event () ainda pode fazer o "código padrão chato", mas em vez de ser virtual, no ponto onde você deseja que ele faça o "novo código interessante", faça com que a classe base chame um método abstrato (ou seja, deve ser substituído). que será fornecido por sua classe descendente.
EDITAR: E se mais tarde você decidir que algumas de suas classes descendentes não precisam fornecer "novo código interessante", você pode alterar o abstrato para virtual e fornecer uma implementação de classe base vazia dessa funcionalidade "inserida".
fonte
Seu compilador pode ter um aviso de que pode ser gerado se uma função de classe base ficar oculta. Em caso afirmativo, ative-o. Isso detectará conflitos constantes e diferenças nas listas de parâmetros. Infelizmente, isso não revelará um erro de ortografia.
Por exemplo, este é o aviso C4263 no Microsoft Visual C ++.
fonte
A
override
palavra-chave C ++ 11, quando usada com a declaração de função dentro da classe derivada, força o compilador a verificar se a função declarada está realmente substituindo alguma função da classe base. Caso contrário, o compilador gerará um erro.Portanto, você pode usar o
override
especificador para garantir o polimorfismo dinâmico (substituição de função).fonte