У меня есть полиморфные классы, полученные из базового класса A:
class A {
public:
virtual void fV() { }
};
class B : public A {
public:
void mB() { }
};
class C : public A {
public:
void mC() { }
};
Теперь я хочу перебрать массив, указывающий на такие объекты, и проверить эквивалентность типов:
A *array[4] = { new B, new C, new C, new B };
for(int i = 0; i < 4; ++i) {
cout << i + 1 << ". " ;
(typeid(array[i]) == typeid(A)) ? cout << 1 << ' ': cout << 0 << ' ';
(typeid(*array[i]) == typeid(B)) ? cout << 1 << ' ': cout << 0 << ' ';
(typeid(*array[i]) == typeid(C)) ? cout << 1 << ' ': cout << 0 << ' ';
cout << endl;
}
Результат:
1. 0 1 0
2. 0 0 1
3. 0 0 1
4. 0 1 0
Я ожидаю эквивалентность типа в первом условии, но в результате я получаю неудачное сравнение (0 0 0 0 в первом столбце). Результаты второго и третьего условия, как я ожидал.
Что не так с первым условием?
Ваш массив определяется как A* array[4]
, Так что тип array[i]
будет A*
,
Следовательно, для второго столбца (первый столбец после индекса):
typeid(array[i]) == typeid(A)
всегда будет ложным (т. е. 0 во втором столбце)typeid(array[i]) == typeid(A*)
всегда будет верно (то есть 1 во втором столбце) typeid(*array[i]) == typeid(A)
может быть правдой, если у вас есть новый элемент A в вашем массиве. Онлайн демо в третьем случае замена одного из производных объектов объектом A.
Внимание: Проверенная эквивалентность типов является строгой эквивалентностью типов. Это верно только для точных совпадений. Это означает, что для второго столбца тест не пройден для объекта, полученного из B. Может быть, это то, что вы ищете, и хорошо. Но это серьезно ограничит расширяемость вашего полиморфного дизайна, если вы намерены просто проверить, следует ли вызывать mB()
или же mC()
, В качестве альтернативы вы можете рассмотреть возможность использования dynamic_cast<>
и проверка, возвращает ли он nullptr или нет
Других решений пока нет …