// File: family.cpp //Experiment with pure virtual functions by Dick Botting November 2000 //Disclaimer... the code embodies rules I selected because they are // interesting to develop not necesarily because they are desirable, // ethical, or real in the author's opinion. If you want to change them // it makes a useful exercise.... do it. #include #include #include using namespace std; class Date{ // worry about this later! int julian; //probably number of days since some starting point. public: Date(int j){julian=j;} Date(){julian=0;} };//Date enum Gender{ UNKNOWN=0, MALE=1, FEMALE=2 }; class Female; //will be derived from abstract Person class Male;//will be derived from abstract Person class Person { //abstract public: virtual Gender gender()const =0;//abstract accessor virtual Person * child()const =0;//abstract accessor virtual void adopts(Person *) =0;//abstract mutator protected: // allows restricted acces by Females and Males to following data Date m_dob; //m_ short for My_... or Member_ string m_name; Person * m_spouse; Person * m_sib; Female * m_mother; //Notice! No m_gender data. Person's don't have gender in abstract. // The concrete Male and Female classes provide the distinction. //Note no constructors for abstract classes. Shared factory method here: void new_Person(string name="Unknown", Date dob=Date(0), Female* mother=NULL) { m_name = name; m_mother=mother; m_dob=dob; m_spouse=m_sib=NULL; } public: Date dob()const {return m_dob;} string name()const {return m_name;} Female* mother()const { return m_mother;} // NULL when mother unknown // Below: NULL if none Person* spouse()const { return m_spouse;} Person* sib()const { return m_sib;} Person* youngest_child()const { Person* child=this-> child(); if(!child)return NULL; for( Person* nxt = child-> sib(); nxt ; nxt = nxt -> sib() ) child = nxt; return child; } Person* elder_sib()const; //events in the life of a person void gets_a_sibling(Person* p){m_sib=p;} // I'd prefer for this to be protected. virtual void marries( Person* p) //assumes genders have been checked { assert( this->unmarried() ); assert( p->unmarried() ); this-> m_spouse=p; p-> m_spouse=this; } void divorces(Person* p) { this-> m_spouse=NULL; p-> m_spouse=NULL; } bool unmarried() { return this-> m_spouse == NULL; } }; class Male: public Person { public: Gender gender()const {return MALE;} void adopts(Person* p); void marries(Person* p); void marries(Female* p){Person::marries((Person*)p); } Person* child()const {return m_spouse->child();} //Constructors Male(){new_Person();} Male(string name){new_Person(name); } Male(string name, Date dob, Female* mother){new_Person(name,dob,mother);} }; class Female: public Person { private: Person * m_child;//first child if any else NULL public: Gender gender()const {return FEMALE;} Person* child()const {return m_child;} void adopts(Person *); void marries(Male* p){Person::marries((Person*)p); } void marries(Person* p); //Constructors Female(string name) { new_Person(name); m_child=NULL; } Female(string name, Date dob, Female* mother) { new_Person(name,dob,mother); m_child=NULL; } Female() { new_Person(); m_child=NULL;} void gives_birth_to(string name, Gender gender, Date dob) { Person* baby; assert(gender!=UNKNOWN); switch(gender) { case MALE: baby = new Male(name,dob,this); break; case FEMALE: baby = new Female(name,dob,this); break; } if(!baby) { cerr << "Unable to allocate more memory\n"; exit(EXIT_FAILURE); //exercise -- replace by exception } this->adopts(baby); } };//end class Female void Female::adopts(Person * p) { if(m_child) ( youngest_child() ) ->gets_a_sibling(p); else m_child = p; } void Male::adopts(Person* p) { if(m_spouse) m_spouse->adopts(p); else { cerr<<"Unmarried males don't adopt children\n";exit(2); } } void Female::marries(Person* p) { assert( p->gender() == MALE ); Person::marries(p); } void Male::marries(Person* p) { assert( p->gender() == FEMALE ); Person::marries(p); } Person* Person::elder_sib()const { Female* my_mother=this-> mother(); if(!my_mother)return NULL; Person* child=my_mother->child(); if(!child)return NULL; for( Person* nxt = child-> m_sib; nxt != this ; nxt = nxt -> m_sib ) child = nxt; return child; } int main() { Male owen("Owen"); Female maureen("Maureen"); owen.marries( &maureen); maureen.gives_birth_to("Kathleen", FEMALE, Date(0)); maureen.gives_birth_to("Kaitlin", FEMALE, Date(0)); cout << owen.child()->name() << endl; cout << owen.youngest_child()->name() << endl; cout << owen.youngest_child()->mother()->name() << endl; }