Encontrando o tipo de um object em C ++

Eu tenho uma class A e outra class que herda dele, B. Eu estou substituindo uma function que aceita um object do tipo A como um parâmetro, então eu tenho que aceitar um A. No entanto, mais tarde eu chamo funções que somente B tem, então eu quero retornar false e não prosseguir se o object passado não for do tipo B.

Qual é a melhor maneira de descobrir qual tipo o object passado para minha function é?

dynamic_cast deve fazer o truque

TYPE& dynamic_cast (object); TYPE* dynamic_cast (object); 

A palavra-chave dynamic_cast converte um datum de um ponteiro ou tipo de referência para outro, executando uma verificação de tempo de execução para garantir a validade da conversão.

Se você tentar converter o ponteiro para um tipo que não seja um tipo de object real, o resultado da conversão será NULL. Se você tentar converter para fazer referência a um tipo que não seja um tipo de object real, o cast lançará uma exceção bad_cast .

Certifique-se de que haja pelo menos uma function virtual na class Base para fazer o dynamic_cast funcionar.

O casting dynamic é o melhor para a sua descrição do problema, mas eu só quero acrescentar que você pode encontrar o tipo de class com:

 #include  ... string s = typeid(YourClass).name() 

Isso é chamado de RTTI, mas você quase certamente quer reconsiderar seu design aqui, porque encontrar o tipo e fazer coisas especiais com base nele torna seu código mais frágil.

Provavelmente, incorpore em seus objects uma “tag” de identificação e use-a para distinguir entre objects da class A e objects da class B.

Isso, no entanto, mostra uma falha no design. Idealmente, esses methods em B, que A não possui, devem ser parte de A, mas deixados em branco, e B os substitui. Isso elimina o código específico da class e está mais no espírito da OOP.

Você está procurando por dynamic_cast(pointer) ?

Apenas para ser completo, vou construir build off do Robocide e ressaltar que typeid pode ser usado sozinho sem usar name ():

 #include  #include  using namespace std; class A { public: virtual ~A() = default; // We're not polymorphic unless we // have a virtual function. }; class B : public A { } ; class C : public A { } ; int main(int argc, char* argv[]) { B b; A& a = b; cout < < "a is B: " << boolalpha << (typeid(a) == typeid(B)) << endl; cout << "a is C: " << boolalpha << (typeid(a) == typeid(C)) << endl; cout << "b is B: " << boolalpha << (typeid(b) == typeid(B)) << endl; cout << "b is A: " << boolalpha << (typeid(b) == typeid(A)) << endl; cout << "b is C: " << boolalpha << (typeid(b) == typeid(C)) << endl; } 

Saída:

 a is B: true a is C: false b is B: true b is A: false b is C: false 

Como os outros indicaram, você pode usar dynamic_cast. Mas, geralmente, usar dynamic_cast para descobrir o tipo da class derivada na qual você está trabalhando indica o design incorreto. Se você está sobrescrevendo uma function que pega o ponteiro de A como parâmetro, então ele deve ser capaz de trabalhar com os methods / dados da própria class A e não deve depender dos dados da class B. No seu caso ao invés de sobrescrever se você Tem certeza de que o método que você está escrevendo funcionará somente com a class B, então você deve escrever um novo método na class B.

Porque sua aula não é polimórfica. Experimentar:

 struct BaseClas { int base; virtual ~BaseClas(){} }; class Derived1 : public BaseClas { int derived1; }; 

Agora BaseClas é polimórfico. Eu mudei a class para struct porque os membros de uma estrutura são públicos por padrão.

Sua descrição é um pouco confusa.

De um modo geral, embora algumas implementações de C ++ possuam mecanismos para isso, você não deve perguntar sobre o tipo. Em vez disso, você deve fazer um dynamic_cast no ponteiro para A. O que isso fará é que, em tempo de execução, o conteúdo real do ponteiro para A será verificado. Se você tiver um B, você obterá o ponteiro para B. Caso contrário, você obterá uma exceção ou nulo.

Use funções sobrecarregadas. Não requer suporte a dynamic_cast ou mesmo RTTI:

 class A {}; class B : public A {}; class Foo { public: void Bar(A& a) { // do something } void Bar(B& b) { Bar(static_cast(b)); // do B specific stuff } }; 

Se você pode acessar a biblioteca de reforço, talvez a function type_id_with_cvr () seja o que você precisa, que pode fornecer o tipo de dados sem remover os constantes, voláteis, & e && modificadores . Aqui está um exemplo simples em C ++ 11:

 #include  #include  int a; int& ff() { return a; } int main() { ff() = 10; using boost::typeindex::type_id_with_cvr; std::cout < < type_id_with_cvr().pretty_name() < < std::endl; std::cout << type_id_with_cvr().pretty_name() < < std::endl; std::cout << typeid(ff()).name() << std::endl; } 

Espero que isso seja útil.