/*---- signature: main: void -> int purpose: playing with arrays and objects and pointers, oh my! compile using: g++ 112lect07-2.cpp PlayerChar.cpp -o 112lect07-2 run using: ./112lect07-2 by: Sharon Tuttle last modified: 2022-10-06 ----*/ #include <cstdlib> #include <iostream> #include <string> #include <cmath> #include "PlayerChar.h" using namespace std; int main() { cout << boolalpha; // static array of PlayerChar objects PlayerChar squad_static[5]; cout << endl << "squad_static contents: " << endl; for (int i=0; i < 5; i++) { cout << squad_static[i].player_to_string() << endl; } // now consider: // here is a dynamically-allocated array // of PlayerChar objects PlayerChar *squad_dynamic; squad_dynamic = new PlayerChar[5]; cout << endl << "squad_dynamic contents: " << endl; for (int i=0; i < 5; i++) { cout << squad_dynamic[i].player_to_string() << endl; } delete [] squad_dynamic; // this is a static array of 5 elements, // each element is of type pointer-to-PlayerChar PlayerChar *squad_ptrs_stat[5]; // it is BAD IDEA to follow pointers-to-objects // that don't point anywhere, // and ALSO a BAD IDEA to assume what is in // a pointer variable that has declared but not // initialized // what do I get if I try to follow the uninitialized // pointers in this array? ...a run-time error; // what if I initialize the pointers first? for (int i=0; i < 5; i++) { squad_ptrs_stat[i] = new PlayerChar("Moo" + to_string(i), 3, 4.4, "finder", 5); } cout << endl << "squad_ptrs_stat contents: " << endl; for (int i=0; i < 5; i++) { cout << squad_ptrs_stat[i]->player_to_string() << endl; } // careful! need to FREE the memory EACH of these // pointers points to when done! for (int i=0; i < 5; i++) { delete squad_ptrs_stat[i]; squad_ptrs_stat[i] = NULL; } // oh, you wanted a DYNAMIC array of pointers // to PlayerChar objects? // squad_ptrs_dyn will be of type // pointer-to-pointer-to-PlayerChar PlayerChar **squad_ptrs_dyn; // making squad_ptrs_dyn point to // a dynamically-allocated // array of 5 pointer-to-Players instances squad_ptrs_dyn = new PlayerChar*[5]; // need these pointers to POINT to something! for (int i=0; i < 5; i++) { squad_ptrs_dyn[i] = new PlayerChar("Baa" + to_string(i), 6, 7.7, "muncher", 8); } cout << endl << "following squad_ptrs_dyn's pointers:" << endl; for (int i=0; i < 5; i++) { cout << squad_ptrs_dyn[i]->player_to_string() << endl; } // OYYYY! need to free those dynamically-allocated // PlayerChar objects AND this dynamically-allocated // array of pointers-to-PlayerChars...! for (int i=0; i < 5; i++) { delete squad_ptrs_dyn[i]; squad_ptrs_dyn[i] = NULL; } // NOW delete the dynamic array of POINTERS to PlayerChars delete [] squad_ptrs_dyn; // some discussion set-up for additional methods // one should explicitly implement in classes // whose data fields involve dynamic memory // (or sometimes even just collections?) cout << endl << "demoing default overloaded assignment operator" << endl << " for classes: " << endl; PlayerChar alphonse("Alphonse", 25, 10.6, "armour", 30); PlayerChar edward = alphonse; // If you assign alphonse to edward, what does that mean? // The default OVERLOADED ASSIGNMENT OPERATOR generated for // PlayerChar copies the value in alphonse's data // fields into edward's data fields. // here, you can see they are in different locations in // memory: cout << "alphonse's address: " << &alphonse << endl; cout << "edward's address: " << &edward << endl; // but they have equivalent data fields: cout << "alphonse's data fields: " << alphonse.player_to_string() << endl; cout << "edward's data fields: " << edward.player_to_string() << endl; // and if you change edward's name field, in ONLY // changes edward's name, it does NOT also // change alphonse's name edward.set_name("Edward"); cout << endl << "after edward's name change: " << endl; cout << "alphonse's data fields: " << alphonse.player_to_string() << endl; cout << "edward's data fields: " << edward.player_to_string() << endl; cout << endl; return EXIT_SUCCESS; }