// variations on the person and student class to demonstrate the use of // pointers to avoid the slicing problem and the need to define a virtual // destructor in the base class to avoid memory leaks. #include #include #include #include using namespace std; // base class for inheritance class person { public: person(const string & s, const string & n) : ssn(s), name(n) { // nothing else to do } person(const person & rhs) : ssn(rhs.ssn), name(rhs.name) { // nothing else to do } person & operator=(const person & rhs) { if (this != &rhs) { ssn = rhs.ssn; name = rhs.name; } return *this; } virtual ~person() { // nothing to do } const string get_name() const { return name; } // had to declare this function to be virtual to get polymorphic behavior virtual string to_string() const { ostringstream out; out << ssn << ", " << name; return out.str(); } private: string ssn; string name; }; // this is a subclass of person that adds a gpa instance variable class student: public person { public: student(const string & s, const string & n, double g) : person(s, n), gpa(g), dashes(person::to_string().size(), '-') { // nothing else to do } student(const student & rhs) : person(rhs), gpa(rhs.gpa), dashes(rhs.dashes) { // nothing else to do } student & operator=(const student & rhs) { if (this != &rhs) { person::operator=(rhs); gpa = rhs.gpa; dashes = rhs.dashes; } return *this; } string to_string() const { ostringstream out; out << person::to_string() << endl << dashes << endl << gpa; return out.str(); } private: double gpa; string dashes; }; int main() { person p1("833-28-2938", "John Doe"); student s1("837-99-2343", "Jane Smith", 3.95); cout << p1.to_string() << endl; cout << s1.to_string() << endl; cout << endl; // polymorphism person & p2 = s1; cout << p2.to_string() << endl; cout << endl; // example of "slicing" (a BIG problem) vector v; v.push_back(p1); v.push_back(s1); for (const person & p : v) { cout << p.to_string() << endl; } cout << endl; // this version works because of the pointers vector v2; v2.push_back(&p1); v2.push_back(&s1); for (const person * p : v2) { cout << p->to_string() << endl; } cout << endl; // this caused a problem without a virtual destructor person * s2 = new student("783-23-8432", "Barney Rubble", 2.85); cout << s2->to_string() << endl; delete s2; cout << endl; // testing copy constructor and assignment operator for person person p3(p1); cout << p3.to_string() << endl; person p4("634-38-2838", "Joe Biden"); p3 = p4; cout << p3.to_string() << endl; cout << p4.to_string() << endl; cout << endl; // testing copy constructor and assignment operator for student student s3(s1); cout << s3.to_string() << endl; student s4("999-99-9999", "Jill Biden", 4.0); s3 = s4; cout << s3.to_string() << endl; cout << s4.to_string() << endl; return 0; }