2013-06-20 16 views
5

ho classe B che eredita da A.Controllo del tipo di oggetto in C++ 11

class A 
{ 
}; 

class B : public A 
{ 
}; 

Ho tre oggetti.

A* a = new A(); 
A* a2 = new B(); 
B* b = new B(); 

Vorrei se il controllo è un oggetto di tipo A, a2 è oggetto di tipo B (non A), e b è oggetto di tipo B.

ho provato digitato confronto, ma non mi dà una risposta corretta.

cout << (typeid(*a) == typeid(A)) << endl; // -> 1 
cout << (typeid(*a2) == typeid(A)) << endl; // -> 1 
cout << (typeid(*b) == typeid(A)) << endl; // -> 0 

cout << (typeid(*a) == typeid(B)) << endl; // -> 0 
cout << (typeid(*a2) == typeid(B)) << endl; // -> 0 
cout << (typeid(*b) == typeid(B)) << endl; // -> 1 

Ho provato il lancio dinamico, ma ho ottenuto errore di compilazione.

B* derived = dynamic_cast<B*>(a); 
if (derived) { 
    cout << "a is B"; 
} 
derived = dynamic_cast<B*>(a2); 
if (derived) { 
    cout << "a2 is B"; 
} 
derived = dynamic_cast<B*>(b); 
if (derived) { 
    cout << "b is B"; 
} 

typename.cpp: In function 'int main(int, char**)': 
typename.cpp:27:36: error: cannot dynamic_cast 'a' (of type 'class A*') to type 'class B*' (source type is not polymorphic) 
    B* derived = dynamic_cast<B*>(a); 
            ^
typename.cpp:31:34: error: cannot dynamic_cast 'a2' (of type 'class A*') to type 'class B*' (source type is not polymorphic) 
    derived = dynamic_cast<B*>(a2); 

Ho usato il getto statico, ma ho sbagliato la risposta.

B* derived = static_cast<B*>(a); 
if (derived) { 
    cout << "a is B"; // -> YES 
} 
derived = static_cast<B*>(a2); 
if (derived) { 
    cout << "a2 is B"; // -> YES 
} 
derived = dynamic_cast<B*>(b); 
if (derived) { 
    cout << "b is B"; // -> YES 
} 

Come posso identificare correttamente il tipo di oggetto in C++11?

+0

'* a' è di tipo' A' e '* b' è di tipo' B' secondo la loro dichiarazione. –

+0

Il cast dinamico funziona solo con il virtuale ma il tuo codice non ha alcuna funzione virtuale. –

+0

La migliore soluzione minima simile al tuo codice: http://coliru.stacked-crooked.com/view?id=7150bf0db7988cf1d2988aba99c72392-3b440a87a52fe2ae7c853c82f4c5144f – chris

risposta

10

Alcune classi sono polimorfiche, alcune non sono polimorfiche.

Una classe polimorfica ha una o più funzioni virtuali (possibilmente ereditate), una classe non polimorfica ha zero funzioni virtuali.

A e B non sono polimorfici.

Una versione polimorfica di A e B esporrà il comportamento desiderato:

#include <iostream> 
#include <typeinfo> 

using namespace std; 

struct A 
{ 
    virtual ~A() {}; // add virtual function 
}; 

class B : public A 
{ 
}; 

A* a = new A(); 
A* a2 = new B(); 
B* b = new B(); 

int main() 
{ 
    cout << (typeid(*a) == typeid(A)) << endl; // -> 1 
    cout << (typeid(*a2) == typeid(A)) << endl; // -> 0 <-- CHANGED 
    cout << (typeid(*b) == typeid(A)) << endl; // -> 0 

    cout << (typeid(*a) == typeid(B)) << endl; // -> 0 
    cout << (typeid(*a2) == typeid(B)) << endl; // -> 1 <-- CHANGED 
    cout << (typeid(*b) == typeid(B)) << endl; // -> 1 
} 

istanze di un negozio di classe polimorfica del tipo dinamico della loro oggetto più derivato in fase di esecuzione.

(Nel tuo esempio a2 è di tipo puntatore-a-A, e sta puntando a un oggetto di tipo A, ma questo oggetto è solo classe base subobject dell'oggetto più dervived di tipo B. Che cosa si vuole ottenere è il tipo di tale oggetto più derivato B quando l'interrogazione a2. per questo è necessario una classe polimorfica.)

questo è il modo polimorfico classi di supporto dynamic_cast e typeid dell'oggetto più derivati ​​(così come virtuali invio della funzione).

Le classi non polimorfiche non hanno questa informazione, quindi possono solo riportare il tipo statico noto in fase di compilazione. Le classi non polimorfiche sono più compatte ed efficienti delle classi polimorfiche. Questo è il motivo per cui non tutte le classi C++ sono polimorfiche. Il linguaggio lascia al programmatore la scelta del compromesso tra prestazioni e funzionalità. Per esempio:

struct X { int x; }; 
struct Y : X {}; 
struct Z : Y {}; 

Sul mio sistema non polimorfica Z è sizeof(Z) == 4 bytes, stessa di un int.

struct X { int x; virtual ~X() {}; }; 
struct Y : X {}; 
struct Z : Y {}; 

Ora dopo aver fatto Z polimorfico, sizeof(Z) == 16 bytes.Quindi un array di Z è ora più grande del 300%, perché ogni istanza di Z deve memorizzare le informazioni sul tipo in fase di esecuzione.

+1

http://stackoverflow.com/questions/17221668/why-do-we-need-to -use-virtual-a-default-invece-of-virtual-a-in-c – prosseek

+2

@Sharth: No, [non è vero] (http://stackoverflow.com/a/17222286/560648); non lo trovi in ​​nessuno dei due casi. –

+0

@LightnessRacesinOrbit, @prosseek: Grazie per la correzione !. Avevo pensato che fosse uno dei motivi principali del caso "= default". –