2013-06-20 17 views
5

Mam klasy B, która dziedziczy A.Sprawdzanie typ obiektu w C++ 11

class A 
{ 
}; 

class B : public A 
{ 
}; 

i mam trzy obiekty.

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

Chciałbym sprawdzić, czy jest obiektem typu A, A2 jest obiektem typu B (nie) i b jest obiektem typu B.

Próbowałem wpisane porównanie, ale nie daje mi poprawnej odpowiedzi.

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 

Próbowałem dynamicznego castingu, ale dostałem błąd kompilacji.

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); 

Użyłem statycznego odlewania, ale odpowiedź jest błędna.

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 
} 

Jak mogę poprawnie zidentyfikować typ obiektu w C++11?

+0

'' a' jest typu 'A' i' * b' jest typu "B" na ich deklarację. –

+0

Funkcja rzutowania dynamicznego działa tylko z wirtualnymi, ale Twój kod nie ma żadnej funkcji wirtualnej. –

+0

Najlepsze minimalne rozwiązanie podobne do kodu: http://coliru.stacked-crooked.com/view?id=7150bf0db7988cf1d2988aba99c72392-3b440a87a52fe2ae7c853c82f4c5144f – chris

Odpowiedz

10

Niektóre klasy są polimorficzne, inne nie są polimorficzne.

Klasa polimorficzna ma jedną lub więcej funkcji wirtualnych (ewentualnie odziedziczonych), klasa nie-polimorficzna ma zero funkcji wirtualnych.

Twoje A i B nie są polimorficzne.

polimorficzny wersja A i B będą wykazywać zachowanie chcesz:

#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 
} 

instancje klasy polimorficznych sklepie dynamiczny rodzaj ich najbardziej pochodzącego obiektu przy starcie.

(W przykładzie a2 jest typu wskaźnik do A, i wskazuje na obiekt typu A, jednak cel ten jest tylko bazowa klasa podobiekt z najbardziej dervived obiektu typu B. Co chcesz dostać to rodzaj tego większość pochodzi obiektu B podczas odpytywania a2. do tego trzeba polimorficzny klasę.)

to jak polimorficzny klas wspierać dynamic_cast i typeid obiektu większość pochodzi (jak również wirtualne wysłanie funkcji).

Klasy nie polimorficzne nie mają tych informacji, więc mogą raportować tylko typ statyczny znany podczas kompilacji. Klasy nie-polimorficzne są bardziej zwarte i wydajne niż klasy polimorficzne. Dlatego nie wszystkie klasy C++ są polimorficzne. Język pozostawia programistom wybór kompromisu między wydajnością i funkcjonalnością. Na przykład:

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

W moim systemie non-polimorficznych Z jest sizeof(Z) == 4 bytes, tak samo jak int.

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

Teraz po dokonaniu Z polimorficzny, sizeof(Z) == 16 bytes.Tak więc tablica Z jest teraz o 300% większa, ponieważ każda instancja Z musi przechowywać informacje o typie w czasie wykonywania.

+1

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

+2

@Sharth: Nie, [to nie prawda] (http://stackoverflow.com/a/17222286/560648); nie dostaniesz go w tym przypadku. –

+0

@LightnessRacesinOrbit, @prosseek: Dziękujemy za korektę !. Myślałem, że był to jeden z głównych powodów przypadku '= default'. –