There are two problems with your code.
One, Element elements[3]; creates an array of Element objects. Not of "objects of classes derived from Element". You cannot store anything other than an Element in such an array, and any attempt to do so results in object slicing: the non-Element part of the source object is sliced away (discarded) and only the Element part makes it in.
If you want dynamic polymorphism, you have to use pointers or references, and usually also dynamic allocation. In your case, this could look something like this:
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);
Or, if you want to avoid copying the objects:
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);
Or just create them directly in the array:
std::unique_ptr<Element> elements[3];
elements[0] = std::make_unique<Car>();
elements[1] = std::make_unique<Adult>();
elements[2] = std::make_unique<Adult>();
Two, you're misinterpreting the result of dynamic_cast. If dynamic_cast succeeds, it returns the pointer cast to the appropriate type. If it fails, it returns a null pointer. Your condition is reversed, as you're interpreting == nullptr as a success. The loop should actually look like this (with the unique_ptrs from point #1 in place):
for(int i = 0; i< numElements; i++){
    if(dynamic_cast<Adult*>(elements[i].get())){
        cout << "Its an adult" << endl;
    }else{
        cout << "Sth else" << endl;
    }
}
A few side notes:
- Since your - Elementis used as a polymorphic base class, it should have a virtual destructor. Otherwise, using a pointer of type- Elementto delete a dynamically allocated object of a type derived from- Elementwill result in Undefined Behaviour (most likely memory corruption).
 
- If your - Elementis intended only as an abstract base and you never expect objects of type exactly- Element(not derived from it) to exist, you should make- Elementabstract by giving it at least one pure virtual function (- virtual void foo() = 0;). If it's a real base class, it will probably naturally contain a few candidates for that.
 
- Needing to know the exact derived type when working with a base class is often a sign of bad design. Ideally, - Elementshould contain virtual functions covering all functionality you may need to do with the objects in a type-abstracted manner. Exceptions exist, of course, but you should probably re-evaluate your design to make sure those- dynamic_castsare actually necessary.