#include <ctime>
#include <string>
#include <iostream>

using namespace std;

class HighSchoolStudent {
// The fields are protected just to save time and not to
// write getters/setters. "In production", fields must
// always be private.
protected:
	string _full_name;
	time_t _dob;
	string _ssn;
public:
	HighSchoolStudent() { }
	HighSchoolStudent(const string name, const time_t dob, const string ssn) {
		init(name, dob, ssn);
	}
	HighSchoolStudent(const HighSchoolStudent &other) {
		init(other._full_name, other._dob, other._ssn);
	}
	void print() const {
		cout << "HighSchoolStudent{ ";
		print_core();
		cout << " }\n";
	}
protected:
	virtual void print_core() const {
		cout << "name = '" << _full_name << "', dob = "
			<< _dob << ", ssn = " << _ssn;
	}
	void init(const string name, const time_t dob, const string ssn) {
		_full_name = name;
		_dob = dob;
		_ssn = ssn;
	}
};

class UniversityStudent : public HighSchoolStudent {
private:
	string _perm_number;
	string _major;
	int _advisor_id;
public:
	UniversityStudent(const string name, const time_t dob, const string ssn,
		const string perm, const string major, const int advisor_id)
		: HighSchoolStudent(name, dob, ssn) {
		init(perm, major, advisor_id);
	}
	UniversityStudent(const UniversityStudent &other) {
		HighSchoolStudent::init(other._full_name, other._dob, other._ssn);
		init(other._perm_number, other._major, other._advisor_id);
	}
	void print_core() const {
		HighSchoolStudent::print_core();
		cout << ", major = '" << _major << ", perm = " << _perm_number
			<< ", advisorID = " << _advisor_id;
	}
private:
	void init(const string perm, const string major, const int advisor_id) {
		_perm_number = perm;
		_major = major;
		_advisor_id = advisor_id;
	}
};

int main() {
	HighSchoolStudent *st = new UniversityStudent(
		"John Doe", 8291985, "ssn-123456789",
		"UC00123", "Computer Science", 556
	);
	st->print();
	return 0;
}
