Есть две проблемы с вашим кодом.
One , Element elements[3];
создает массив из Element
объектов.Не из "объектов классов, производных от Element
".Вы не можете хранить ничего, кроме Element
в таком массиве, и любая попытка сделать это приводит к разрезанию объекта : часть, отличная от Element
исходного объекта, удаляется (отбрасывается) итолько часть Element
делает это.
Если вы хотите динамический полиморфизм, вы должны использовать указатели или ссылки, и обычно также динамическое выделение.В вашем случае это может выглядеть примерно так:
std::unique_ptr<Element> elements[3];
Car c;
Adult a1;
Adult a2;
elements[0] = std::make_unique<Car>(c);
elements[1] = std::make_unique<Adult>(a1);
elements[2] = std::make_uniuqe<Adult>(a2);
Или, если вы хотите избежать копирования объектов:
std::unique_ptr<Element> elements[3];
auto c = std::make_unique<Car>();
auto a1 = std::make_unique<Adult>();
auto a2 = std::make_unique<Adult>();
elements[0] = std::move(c);
elements[1] = std::move(a1);
elements[2] = std::move(a2);
Или просто создать их непосредственно в массиве:
std::unique_ptr<Element> elements[3];
elements[0] = std::make_unique<Car>();
elements[1] = std::make_unique<Adult>();
elements[2] = std::make_unique<Adult>();
Два , вы неправильно интерпретируете результат dynamic_cast
.Если dynamic_cast
завершается успешно, он возвращает приведение указателя к соответствующему типу.Если это не удается, он возвращает нулевой указатель.Ваше состояние полностью изменено, поскольку вы интерпретируете == nullptr
как успех.Цикл должен фактически выглядеть следующим образом (с unique_ptr
s из точки # 1 на месте):
for(int i = 0; i< numElements; i++){
if(dynamic_cast<Adult*>(elements[i].get())){
cout << "Its an adult" << endl;
}else{
cout << "Sth else" << endl;
}
}
Несколько примечаний:
Поскольку ваш Element
используется как полиморфный базовый класс, он должен иметь виртуальный деструктор.В противном случае использование указателя типа Element
для удаления динамически размещенного объекта типа, производного от Element
, приведет к неопределенному поведению (наиболее вероятному повреждению памяти).
Если вашElement
предназначено только как абстрактная база, и вы никогда не ожидаете, что объекты типа Element
(не производные от него) существуют, вы должны сделать Element
абстрактным, предоставив ему хотя бы одну чисто виртуальную функцию (virtual void foo() = 0;
)).Если это настоящий базовый класс, он, вероятно, будет содержать несколько кандидатов для этого.
Необходимость знать точный производный тип при работе с базовым классом часто является признаком плохого дизайна.,В идеале Element
должен содержать виртуальные функции, охватывающие все функции, которые вам могут понадобиться для объектов с абстракцией типа.Конечно, существуют исключения, но вам, вероятно, следует пересмотреть свой дизайн, чтобы убедиться, что эти dynamic_casts
действительно необходимы.