dichiarazione anticipata e typeid
-
20-09-2019 - |
Domanda
Vorrei verificare il tipo di un A
superclasse contro il tipo di un B
sottoclasse (con un metodo all'interno del A
superclasse, in modo che B
erediterà esso).
Ecco quello che ho pensato che ha fatto il trucco (vale a dire, l'uso di dichiarazione anticipata):
#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;
}
Tuttavia questo codice non viene compilato. L'errore che ottengo è:
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’
Come potrei risolvere questo problema?
Soluzione
Credo che il problema che si sta tentando di risolvere è molto meglio gestita da un metodo virtuale:
class A
{
public:
virtual bool Check() { return false; };
}
class B : public A
{
public:
// override A::Check()
virtual bool Check() { return true; };
}
I metodi della classe base A non dovrebbe essere necessario sapere se l'oggetto è "realmente" una A o una B. Questo è una violazione dei principi di base orientati agli oggetti di design. Se il comportamento deve cambiare quando l'oggetto è un B, allora quel comportamento dovrebbe essere definito in B e gestito da chiamate metodo virtuale.
Altri suggerimenti
Basta muovere la definizione di Check () fuori dal corpo di 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;
}
Un modo sarebbe quello di tirare la definizione di Check
fuori della definizione della classe, in modo che B
viene definita quando il compilatore arriva alla definizione di funzione.
class A {
//...
void Check();
//...
};
class B { /* ... */ };
void A::Check() {
//...
}
Sposta il definizione del Controlla qui sotto la tua dichiarazione di classe B.
Basta muovere il corpo della funzione dopo la dichiarazione di 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;
}
Ciao, anche se si mette la definizione di A :: Controllare al di fuori della classe il risultato non sarà quello che vi aspettate. Questo perché l'oggetto B questo convertire in un oggetto nel metodo così questo indica una Un oggetto così i typeids sempre diverse. Per risolvere questo dichiarare il metodo virtuale.
Comunque, io continuo a non capire perché si vuole eseguire tale O_o di prova ?? E come ha detto CAdaker questo non è buona pratica