Qual é o método preferido para obter o equivalente em C ++ dos java's instanceof
?
java
c++
oop
instanceof
Yuval Adam
fonte
fonte
Respostas:
Tente usar:
Isso requer que seu compilador tenha o suporte a rtti ativado.
EDIT: Eu tive alguns bons comentários sobre esta resposta!
Toda vez que você precisar usar um dynamic_cast (ou instanceof), é melhor você se perguntar se é necessário. Geralmente é um sinal de mau design.
As soluções alternativas típicas são colocar o comportamento especial da classe que você está verificando em uma função virtual na classe base ou talvez introduzir algo como um visitante em que você possa introduzir um comportamento específico para subclasses sem alterar a interface (exceto adicionar a interface de aceitação do visitante de curso).
Como apontado, o dynamic_cast não é de graça. Um hack simples e de desempenho consistente que lida com a maioria (mas não todos os casos) é basicamente adicionar uma enumeração que representa todos os tipos possíveis que sua classe pode ter e verificar se você acertou.
Isso não é bom para o design, mas pode ser uma solução alternativa e seu custo é mais ou menos apenas uma chamada de função virtual. Também funciona, independentemente de o RTTI estar ativado ou não.
Observe que essa abordagem não oferece suporte a vários níveis de herança; portanto, se você não tomar cuidado, poderá terminar com um código parecido com o seguinte:
fonte
Dependendo do que você deseja fazer, você pode fazer o seguinte:
Usar:
No entanto, isso opera puramente nos tipos conhecidos pelo compilador.
Editar:
Este código deve funcionar para ponteiros polimórficos:
Exemplo: http://cpp.sh/6qir
fonte
Instância de implementação sem dynamic_cast
Eu acho que essa questão ainda é relevante hoje. Usando o padrão C ++ 11, agora você pode implementar uma
instanceof
função sem usar odynamic_cast
seguinte:Mas você ainda depende do
RTTI
suporte. Então, aqui está minha solução para esse problema, dependendo de algumas macros e da metaprogramação mágica. A única desvantagem é que essa abordagem não funciona para herança múltipla .InstanceOfMacros.h
Demo
Você pode usar esse material ( com cuidado ) da seguinte maneira:
DemoClassHierarchy.hpp *
O código a seguir apresenta uma pequena demonstração para verificar o comportamento correto rudimentar.
InstanceOfDemo.cpp
Resultado:
atuação
A questão mais interessante que surge agora é se esse material maligno é mais eficiente do que o uso
dynamic_cast
. Portanto, eu escrevi um aplicativo de medição de desempenho muito básico.InstanceOfPerformance.cpp
Os resultados variam e baseiam-se essencialmente no grau de otimização do compilador. Compilar o programa de medição de desempenho usando
g++ -std=c++11 -O0 -o instanceof-performance InstanceOfPerformance.cpp
a saída na minha máquina local foi:Mhm, esse resultado foi muito preocupante, porque os horários demonstram que a nova abordagem não é muito mais rápida em comparação com a
dynamic_cast
abordagem. É ainda menos eficiente para o caso de teste especial que testa se um ponteiro deA
é uma instância deA
. MAS a maré vira ajustando nosso binário usando otimização do compilador. O respectivo comando do compilador ég++ -std=c++11 -O3 -o instanceof-performance InstanceOfPerformance.cpp
. O resultado na minha máquina local foi incrível:Se você não depende de herança múltipla, não se opõe a boas macros C antigas, RTTI e metaprogramação de modelos e não tem preguiça de adicionar algumas instruções pequenas às classes de sua hierarquia de classes, essa abordagem pode aumentar um pouco seu aplicativo com relação ao seu desempenho, se você costuma verificar a instância de um ponteiro. Mas use-o com cautela . Não há garantia para a correção dessa abordagem.
Nota: Todas as demos foram compiladas usando o
clang (Apple LLVM version 9.0.0 (clang-900.0.39.2))
macOS Sierra em um MacBook Pro meados de 2012.Edit: Eu também testei o desempenho em uma máquina Linux usando
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
. Nesta plataforma, o benefício de desempenho não era tão significativo quanto nos macOs com clang.Saída (sem otimização do compilador):
Saída (com otimização do compilador):
fonte
dynamic_cast
é conhecido por ser ineficiente. Ele percorre a hierarquia de herança e é a única solução se você tiver vários níveis de herança e precisa verificar se um objeto é uma instância de qualquer um dos tipos em sua hierarquia de tipos.Mas se uma forma mais limitada
instanceof
disso apenas verificar se um objeto é exatamente do tipo especificado, é suficiente para suas necessidades, a função abaixo seria muito mais eficiente:Aqui está um exemplo de como você chamaria a função acima:
Você especificaria o tipo de modelo
A
(como o tipo que está verificando) e passaria o objeto que deseja testar como argumento (a partir do qual o tipo de modeloK
seria inferido).fonte
fonte
instanceof
consulta o tipo dinâmico, mas nesta resposta o tipo dinâmico e estático sempre corresponde.Isso funcionou perfeitamente para mim usando o Code :: Blocks IDE com complemento do GCC
fonte
typeid
", que enquanto incorreta ("Não há garantia de que a mesma instância std :: type_info seja referida por todas as avaliações da expressão typeid no mesmo tipo ...assert(typeid(A) == typeid(A)); /* not guaranteed */
", consulte cppreference.com ), indica que ele tentou pelo menos responder à pergunta, se não ajudou , porque deixou de oferecer um exemplo de trabalho mínimo.