Below snippet to usage of pointers,
Car obj;
Car *p_Obj = &obj;
Car **pp_Obj = &p_obj;
obj
is simple object which stored the content.
p_Obj
is pointer and is pointing to memory location of obj
pp_Obj
is a pointer to a pointer to obj
In short,

Now coming to your case,
Car cars1_[numCars];
Car * cars2_;
Car * cars3_[numCars];
Car ** cars4_;
cars1
is array of object. As you pointed out individual object can be accessed as cars1_[0].fun()

cars2_
is a pointer to an object or array of object. assigned or updated as below,
Car cars1_;
Car * cars2_ = &cars1_;
cars2_ -> fun();
// or
Car cars1_[numCars];
Car * cars2_ = cars1_;
cars2_[0].fun();

cars3_
is a array of a pointers to object or array of objects
Car cars11_{10};
Car cars12_[4]{20,30,40};
Car * cars2_[4] = { &cars11_,&cars12_[0] };
cars2_[0]->fun(); //access cars11_
(cars2_[1]+0)->fun(); //access cars12_[0]
(cars2_[1]+1)->fun(); //access cars12_[1]
(cars2_[1]+2)->fun(); //access cars12_[2]
//or
cars2_[1][0].fun(); //access cars12_[0]
cars2_[1][1].fun(); //access cars12_[1]
cars2_[1][2].fun(); //access cars12_[2]

cars4_
is a pointer to a pointer to a object or pointer to a array of pointers to a object or pointer to a pointer to a array of object
Car cars11_[4]{10,20,30};
Car *cars12_= &cars11_[0];
Car **cars4_ = &cars12_;
(*cars4_)[0].fun(); //access cars11_[0]
(*cars4_)[1].fun(); //access cars11_[1]
(*cars4_)[2].fun(); //access cars11_[2]
//or
cars4_[0][0].fun(); //access cars11_[0]
cars4_[0][1].fun(); //access cars11_[1]
cars4_[0][2].fun(); //access cars11_[1]
