У меня есть класс B, который наследует от A.
class A
{
};
class B : public A
{
};
И у меня есть три объекта.
A* a = new A();
A* a2 = new B();
B* b = new B();
Я хотел бы, чтобы проверить, является ли объект типа A, a2 является объектом типа B (не A), а 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?
Некоторые классы полиморфны, некоторые не полиморфны.
Полиморфный класс имеет одну или несколько виртуальных функций (возможно, унаследованных), а неполиморфный класс имеет ноль виртуальных функций.
Ваши А и Б не полиморфны.
Полиморфная версия 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, и указывает на объект типа A, однако этот объект является только подобъект базового класса из самый дервивированный объект типа 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
Экземпляр должен хранить информацию о своем типе во время выполнения.
Других решений пока нет …