2013-06-20 4 views
5

У меня есть класс B, который наследуется от А.Проверка типа объекта в C++ 11

class A 
{ 
}; 

class B : public A 
{ 
}; 

И у меня есть три объекта.

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

Я хотел бы, если проверка а является объектом типа А, а2 является объектом типа B (не А), и б является объектом типа B.

Я попытался набран сравнение, но это не дает мне правильного ответа.

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 

Я пробовал динамическое кастинг, но я получил ошибку компиляции.

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

Я использовал статическое кастинг, но я получил ответ неправильно.

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 
} 

Как правильно определить тип объекта в C++11?

+0

'* a' имеет тип' A' и '* b' имеет тип' B' за их объявление. –

+0

Динамический кастинг будет работать только с виртуальными, но ваш код не имеет виртуальной функции. –

+0

Наилучшее минимальное решение, подобное вашему коду: http://coliru.stacked-crooked.com/view?id=7150bf0db7988cf1d2988aba99c72392-3b440a87a52fe2ae7c853c82f4c5144f – chris

ответ

10

Некоторые классы являются полиморфными, некоторые не являются полиморфными.

Полиморфный класс имеет одну или несколько виртуальных функций (возможно, унаследован), не полиморфный класс имеет нулевые виртуальные функции.

Ваши A и B не являются полиморфными.

полиморфный вариант А и В будет демонстрировать поведение, которое вы хотите:

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

Случаи полиморфного класс магазин динамического типа их наиболее производного объекта во время выполнения.

(В вашем примере a2 имеет тип указателя на-A, и указывает на объект типа А, однако этот объект является только класс субобъект база из наиболее dervived объекта типа B. То, что вы хотите получить тип этого сам производного объекта B при запросе a2. для этого нужно полиморфный класс.)

Вот как полиморфные классы поддерживают dynamic_cast и typeid сам объект производного (как и виртуальные функция отправки).

Неполиморфные классы не имеют этой информации, поэтому они могут сообщать только статический тип, известный во время компиляции. Неполиморфные классы более компактны и эффективны, чем полиморфные классы. Вот почему не все классы C++ являются полиморфными. Язык оставляет программисту возможность выбрать компромисс между производительностью и функциональностью. Например:

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

В моей системе без полиморфного Z является sizeof(Z) == 4 bytes, так же как int.

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

Теперь после создания Z полиморфных, sizeof(Z) == 16 bytes.Таким образом, массив Z теперь на 300% больше, потому что каждый экземпляр Z должен хранить информацию о типе во время выполнения.

+1

http://stackoverflow.com/questions/17221668/why-do-we-need-to -use-virtual-a-default-вместо-virtual-a-in-c – prosseek

+2

@Sharth: Нет, [это неправда] (http://stackoverflow.com/a/17222286/560648); вы не получите его в любом случае. –

+0

@LightnessRacesinOrbit, @prosseek: Спасибо за исправление !. Я думал, что это была одна из главных причин для случая '= default'. –

Смежные вопросы