Declaração e TypeId para a frente
-
20-09-2019 - |
Pergunta
Eu gostaria de verificar o tipo de superclasse A
contra o tipo de subclasse B
(com um método dentro da superclasse A
, para que B
irá herdar).
Aqui está o que eu pensei que fiz o truque (isto é, o uso da declaração avançada):
#include <iostream>
#include <typeinfo>
using namespace std;
class B;
class A {
public:
int i_;
void Check () {
if (typeid (*this) == typeid (B))
cout << "True: Same type as B." << endl;
else
cout << "False: Not the same type as B." << endl;
}
};
class B : public A {
public:
double d_;
};
int main () {
A a;
B b;
a.Check (); // should be false
b.Check (); // should be true
return 0;
}
No entanto, este código não compila. O erro que recebo é:
main.cc: In member function ‘void A::Check()’:
main.cc:12: error: invalid use of incomplete type ‘struct B’
main.cc:6: error: forward declaration of ‘struct B’
Como eu poderia resolver esse problema?
Solução
Eu acho que o problema que você está tentando resolver é muito melhor tratado por um método virtual:
class A
{
public:
virtual bool Check() { return false; };
}
class B : public A
{
public:
// override A::Check()
virtual bool Check() { return true; };
}
Os métodos na classe Base A não precisam saber se o objeto é "realmente" um A ou A B. Isso é uma violação dos princípios básicos de design orientados a objetos. Se o comportamento precisar mudar quando o objeto for B, esse comportamento deve ser definido em B e tratado por chamadas de método virtual.
Outras dicas
Basta mover a definição de check () para fora do corpo de A:
#include <iostream>
#include <typeinfo>
using namespace std;
class B;
class A {
public:
int i_;
void Check ();
};
class B : public A {
public:
double d_;
};
void A::Check () {
if (typeid (*this) == typeid (B))
cout << "True: Same type as B." << endl;
else
cout << "False: Not the same type as B." << endl;
}
int main () {
A a;
B b;
a.Check (); // should be false
b.Check (); // should be true
return 0;
}
Uma maneira seria puxar a definição de Check
fora da definição de classe, de modo que B
é definido quando o compilador chega à definição da função.
class A {
//...
void Check();
//...
};
class B { /* ... */ };
void A::Check() {
//...
}
Mova sua definição da verificação abaixo da sua declaração da classe B.
Basta mover o corpo da função após a declaração de B.
#include <iostream>
#include <typeinfo>
struct A
{
int i_;
void Check();
};
struct B : A
{
double d_;
};
void A::Check()
{
using namespace std;
if (typeid (*this) == typeid (B))
{
cout << "True: Same type as B." << endl;
}
else
{
cout << "False: Not the same type as B." << endl;
}
}
int main()
{
A a;
B b;
a.Check(); // should be false
b.Check(); // should be true
return 0;
}
Olá, mesmo se você colocar a definição de A :: Check fora da classe, o resultado não será o que você espera. Isso ocorre porque o objeto B que isso é convertido para um objeto A no método, para que este ponto em um objeto A, portanto, os tipos são sempre diferentes. Para resolver isso, declare o método virtual.
No entanto, ainda não entendo por que você quer realizar esse teste O_O ?? E como o Cadaker disse que isso não é uma boa prática