// Author: Carol Conway revision 4/12/21 // Program is loosely based on an example from an older Gaddis textbook // This program demonstrates use of the Car, Truck, and SUV // classes that are derived from the base Automobile class. // It also has a SportCar class that is derived from the Car class // this version implements a virtual function in the base class that displays automobile attributes // Each subclass has its own overridden output function // Another feature of this program is the use of a vector of pointers to the base class // Each pointer points to dynamically allocated memory of different subclass types // The program uses polymorphism to select which function to use for output. // In addition it illustrates the use of a base class destructor. #include #include #include #include "Automobile.h" #include "Car.h" #include "Truck.h" #include "SUV.h" #include "SportCar.h" using namespace std; //added to the example by CYC //the vector contains base class-type elements so cars, SUVs and trucks can //be added to the vector because each IS an automobile. //void displayFleet( const vector *inv ); //global fcn using pointer syntax //sets up a vector named inv which contains pointer to Automobile objects //the & simply refers to a pass-by-reference parameter void displayFleet( const vector &inv ); //prototype for a non-class fcn using ref syntax // void displayFleet (const Automobile inv[] int size); int main() { vector inventory; //Vector OF POINTERS to vehicles of different subclasses // Automobile *inventoryArray[10] //an array of pointers to objects //create derived class objects at run by using the new operator which returns a pointer to the data // Create a Car object for a used 2019 BMW with // 38,000 miles, priced at $22,000, with 4 doors. Car *carPtr = new Car("BMW", 2019, 22000, 38000.0, 4); inventory.push_back(carPtr); //add this car to the inventory vector // inventoryArray[0] = carPtr; //this is what code looks like using an array // Create a Truck object for a used 2006 Toyota // pickup with 40,000 miles, priced at $5,000, // with 4-wheel drive. Truck *truckPtr = new Truck("Toyota", 2006, 40000, 5000.0, "4WD","Extended"); inventory.push_back(truckPtr); //added to vector at end // Create an SUV object for a used 2015 Volvo // with 30,000 miles, priced at $18,000, with // 5 passenger capacity. SUV *suvPtr = new SUV("Volvo", 2015, 30000, 18000.00, 6); inventory.push_back(suvPtr); //added to vector at end // Create a 2nd Truck object for a new Ford F150 regular cab // pickup with 25 miles, priced at $37,500, // with 4-wheel drive. Truck *truckPtr2 = new Truck("Ford F150", 2021, 25, 37500.0, "2WD","Regular"); inventory.push_back(truckPtr2); //added to vector at end //create a sports car model SportCar *sportCarPtr = new SportCar("Porsche", 2017, 60000, 32850, 2, 220); inventory.push_back(sportCarPtr); //display all vehicles polymorphically using main line loop in code cout << "Displaying all vehicles from a loop in main()\n"; for (unsigned i = 0; i < inventory.size(); ++i) { //this is like saying inventory[i]->displayVehicleInfo() //which display function runs? Answer: the function that is associated //with the derived class object being pointed to! //This is runtime polymorphism demo'ed inventory.at(i)->displayVehicleInfo(); // inventory[i]->displayVehicleInfo(); //array access cout << endl; } cout << endl; //redisplay all vehicles by calling the global function displayFleet() cout << "Re-displaying all vehicles using a function\n"; displayFleet(inventory); //this is inventory using call by reference with vector arg // displayFleet(inventory, size); // if inventory were an array // delete all allocated memory for (unsigned i = 0; i < inventory.size(); ++i) { delete inventory.at(i); //causes the base class virtual destructor to execute } cout << "After deleting all allocated memory Inventory still contains " << inventory.size() << " meaningless items" << endl; //resize the vector back to zero because the pointers present in the vector are still there, even //though they cannot access meaningful data anymore. inventory.clear(); cout << "After clearing the vector, Inventory now contains " << inventory.size() << " items" << endl; return 0; }; //end main() //displayFleet displays the dereferenced contents of the vector of pointers to the various vehicles //The vector must be passed by reference or by pointer. I used references as it is easier. //to use pointers you must use pointer notation to invoke the //size and the at() vector member functions //void displayFleet(const vector *inv ) void displayFleet(const vector &inv ) //reference syntax { for (unsigned i = 0; i < inv.size(); ++i) //this would be inv->size() with ptrs { inv.at(i)->displayVehicleInfo(); //ptr notation used because this is a vector of pointers cout << endl; } }