CS 250 Computer Programming and Problem Solving - FALL 1998 |
---|
[ Home | Syllabus | Notes | Glossary | CS250 WEB Version Home Page ]
Inheritance (IS-A Relationships
Inheritance (IS-A Relationship)
An IS-A relationship exists between two classes when one class is a specialization of the other.
For Example, A Student is a Person, A Book is a Publication, A Magazine is a Publication
Specializing a class reuses the original class while allowing you to customize the new class
Derived Classes (Inheritance Relationship)
Description | To form an inheritance relationship between two classes,
the more general class is called the Base Class and the Specialization is called
the Derived Class A derived class is used as if the two classes have been combined A derived class can add new members (both functions and data) or override a existing member of the base class |
Syntax | class derivedClassName : public
baseClassName { .... } class derivedClassName : private baseClassName { .... } |
Examples (more examples) |
class ClassA { public: ClassA( ); void setVar1(int x); int getVar1( ) const; private: int Var1; } class ClassB: public ClassA
{ ClassB someObject; |
Tips |
|
// p184.txt - Order of constructors, Section 6.1.2.2.
#include <iostream.h> // demonstrate order of construction // what would be printed?
#include <iostream.h>
class ClassA { public: ClassA() { cout << "ClassA,"; } };
class ClassB { public: ClassB() { cout << "ClassB,"; } private: ClassA x; ClassA y; };
class ClassC :public ClassB { public: ClassC() { cout << "ClassC,"; } private: ClassA z; };
class ClassD { public: ClassD() { cout << "ClassD,"; } };
class ClassE :public ClassD { public: ClassE() { cout << "ClassE"; } private: ClassC center; int radius; };
void main() { ClassE S; }
// P179.txt - Single Inheritance, Section 6.1.1.
#include "fstring.h"
class Publication { public: void SetPublisher( const FString & p ); void SetDate( unsigned long dt ); private: FString publisher; // Define state of a Publication unsigned long date; };
class Magazine :public Publication { // specialize Publication to Magazine public: void SetIssuesPerYear( unsigned n ); void SetCirculation( unsigned long n ); private: // has publisher and date from base class - plus these new members unsigned issuesPerYear; unsigned long circulation; };
class Book :public Publication {// specialize Publication to Book public: void SetISBN( const FString & s ); void SetAuthor( const FString & s ); private: // has publisher and date from base class - plus these new members FString ISBN; FString author; };
int main() { Book B; B.SetPublisher( "Prentice Hall" ); B.SetDate( 970101L ); B.SetISBN( "0-02-359852-2" ); B.SetAuthor( "Irvine, Kip" );
Magazine M; M.SetIssuesPerYear( 12 ); M.SetCirculation( 500000L ); M.SetPublisher("Time Warner Inc");
return 0; }
Here is a example comparing HasA and IsA relationships
Class Relationships
Case Study: Student/Person (Has-A)
Let's assume you have a Person class defined as follows
//*********************************************************** // Person: Small example to show various relationships // Attributes implemented: // Name: Uses Name Class // SSN: uses FixedString // Age: integer // We could add many more attributes like addresses // - but this is enough to illustrate // // Programmer: Chris Wild //************************************************************
#ifndef PERSON_H #define PERSON_H #include "Name.h" #include "FixedString.h"
class Person { friend ostream & operator <<(ostream & outFile, const Person & thisPerson); friend istream & operator >>(istream & inFile, Person & thisPerson); public: Person(); Person(const FixedString & theFirst, const FixedString & theLast, const FixedString & theSSN, int theAge);
//****** Modifiers and Selectors void SetFirstName(const FixedString & theName); FixedString GetFirstName() const; void SetLastName(const FixedString & theName); FixedString GetLastName() const; void SetSSN(const FixedString & theSSN); FixedString GetSSN() const; void SetAge(int theAge); int GetAge() const;
private: Name myName; FixedString mySSN; int myAge; }; #endif
//************************************************ // Student: defines a Student class with attributes // Personal: personal data - uses Person class // GPA: Grade Point Average // Major: FixedString - uses "undeclared" until major is known // // Programmer: Chris Wild //*************************************************
#ifndef STUDENT_H #define STUDENT_H
#include "Person.h" #include "FixedString.h" // why needed?
class Student { friend ostream & operator <<(ostream & outFile, const Student & thisStudent); friend istream & operator >>(istream & inFile, Student & thisStudent); public: Student(); //POST: Sets GPA to 0 and Major to "undeclared" // Personal information set to its default values Student(const Person & thePerson, float theGPA, FixedString theMajor);
//***** modifiers and selectors void SetPerson(const Person & thePerson); Person GetPerson() const; void SetGPA(float GPA); float GetGPA() const; void SetMajor(const FixedString & theMajor); FixedString GetMajor() const;
private: Person myPerson; float myGPA; FixedString myMajor; }; #endif
#include "Student.h" #include "Person.h" #include "FixedString.h" #include <iostream.h>
void main() { Student chrisStudent; cout << " initially Chris:\n" << chris << endl << endl; Person chrisPerson; chrisPerson.SetFirstName("Chris"); chrisPerson.SetLastName("Wild"); chrisPerson.SetAge(51); chrisPerson.SetSSN("000-00-0000"); chrisStudent.SetPerson(chrisPerson); chrisStudent.SetGPA(4.0); chrisStudent.SetMajor("Computer Science"); cout << "after setting Chris:\n" << chrisStudent << endl << endl; }
Class Relationships
Case Study: Student/Person (Has-A : Version 2)
//************************************************ // Student: defines a Student class with attributes // Personal: personal data - uses Person class // GPA: Grade Point Average // Major: FixedString - uses "undeclared" until major is known // // Programmer: Chris Wild //*************************************************
#ifndef STUDENT_H #define STUDENT_H
#include "Person2.h" #include "FixedString.h" // why needed?
class Student { friend ostream & operator <<(ostream & outFile, const Student & thisStudent); friend istream & operator >>(istream & inFile, Student & thisStudent); public: Student(); //POST: Sets GPA to 0 and Major to "undeclared" // Personal information set to its default values Student(const FixedString & theFirstName, const FixedString & theLastName, const FixedString & theSSN, int theAge, float theGPA, FixedString theMajor);
//***** modifiers and selectors void SetFirstName(const FixedString & theName); FixedString GetFirstName() const; void SetLastName(const FixedString & theName); FixedString GetLastName() const; void SetSSN(const FixedString & theSSN); FixedString GetSSN() const; void SetAge(int theAge); int GetAge() const; void SetGPA(float GPA); float GetGPA() const; void SetMajor(const FixedString & theMajor); FixedString GetMajor() const;
private: Person myPerson; float myGPA; FixedString myMajor; }; #endif
#include "Student2.h" #include <iostream.h>
void main() { Student chris; cout << " initially Chris:\n" << chris << endl << endl;
chris.SetFirstName("Chris"); chris.SetLastName("Wild"); chris.SetAge(51); chris.SetSSN("000-00-0000"); chris.SetGPA(4.0); chris.SetMajor("Computer Science"); cout << "after setting Chris:\n" << chris << endl << endl;
}
#include "Student2.h"
ostream & operator <<(ostream & outFile, const Student & thisStudent) { outFile << thisStudent.myPerson << "GPA: " << thisStudent.myGPA << endl << "Major: " << thisStudent.myMajor << endl; return outFile; }
istream & operator >>(istream & inFile, Student & thisStudent) { inFile >> thisStudent; cout << "GPA: "; inFile >> thisStudent.myGPA; inFile.ignore(); // linefeed cout << "Major: "; inFile >> thisStudent.myMajor; return inFile; }
//**** Constructors Student::Student() { myGPA = 0.0; myMajor = "undeclared"; }
Student::Student(const FixedString & theFirstName, const FixedString & theLastName, const FixedString & theSSN, int theAge, float theGPA, FixedString theMajor) { myPerson.SetFirstName(theFirstName); myPerson.SetLastName(theLastName); myPerson.SetSSN(theSSN); myPerson.SetAge(theAge); myGPA = theGPA; myMajor = theMajor; }
//***** modifiers and selectors void Student::SetFirstName(const FixedString & theName) { myPerson.SetFirstName(theName); } FixedString Student::GetFirstName() const { return myPerson.GetFirstName(); } void Student::SetLastName(const FixedString & theName) { myPerson.SetLastName(theName); } FixedString Student::GetLastName() const { return myPerson.GetLastName(); } void Student::SetSSN(const FixedString & theSSN) { myPerson.SetSSN(theSSN); } FixedString Student::GetSSN() const { return myPerson.GetSSN(); } void Student::SetAge(int theAge) { myPerson.SetAge(theAge); } int Student::GetAge() const { return myPerson.GetAge(); }
void Student::SetGPA(float theGPA) { myGPA = theGPA; } float Student::GetGPA() const { return myGPA; } void Student::SetMajor(const FixedString & theMajor) { myMajor = theMajor; } FixedString Student::GetMajor() const { return myMajor; }
Class Relationships
Case Study: Student/Person (Is-A)
//************************************************ // Student: defines a Student class with attributes // Personal: personal data - uses Person class // GPA: Grade Point Average // Major: FixedString - uses "undeclared" until major is known // // Programmer: Chris Wild //*************************************************
#ifndef STUDENT_H #define STUDENT_H
#include "Person3.h" #include "FixedString.h" // why needed?
class Student: public Person { friend ostream & operator <<(ostream & outFile, const Student & thisStudent); friend istream & operator >>(istream & inFile, Student & thisStudent); public: Student(); //POST: Sets GPA to 0 and Major to "undeclared" // Personal information set to its default values Student(const FixedString & theFirstName, const FixedString & theLastName, const FixedString & theSSN, int theAge, float theGPA, FixedString theMajor);
//***** modifiers and selectors
void SetGPA(float GPA); float GetGPA() const; void SetMajor(const FixedString & theMajor); FixedString GetMajor() const;
private: // Notice we only add new data members // all existing data and function members of Person are inherited float myGPA; FixedString myMajor; }; #endif
#include "Student3.h"
ostream & operator <<(ostream & outFile, const Student & thisStudent) { outFile << (Person &) thisStudent << "GPA: " << thisStudent.myGPA << endl << "Major: " << thisStudent.myMajor << endl; return outFile; }
istream & operator >>(istream & inFile, Student & thisStudent) { inFile >> (Person &) thisStudent; cout << "GPA: "; inFile >> thisStudent.myGPA; inFile.ignore(); // linefeed cout << "Major: "; inFile >> thisStudent.myMajor; return inFile; }
//**** Constructors Student::Student() { myGPA = 0.0; myMajor = "undeclared"; }
Student::Student(const FixedString & theFirstName, const FixedString & theLastName, const FixedString & theSSN, int theAge, float theGPA, FixedString theMajor) { SetFirstName(theFirstName); SetLastName(theLastName); SetSSN(theSSN); SetAge(theAge); // we can call member functions of the base class // why needed? because data members are still private!! myGPA = theGPA; myMajor = theMajor; }
//***** modifiers and selectors // only worry about new fields
void Student::SetGPA(float theGPA) { myGPA = theGPA; } float Student::GetGPA() const { return myGPA; } void Student::SetMajor(const FixedString & theMajor) { myMajor = theMajor; } FixedString Student::GetMajor() const { return myMajor; }
#include "Student3.h" #include <iostream.h>
void main() { Student chris; cout << " initially Chris:\n" << chris << endl << endl;
chris.SetFirstName("Chris"); chris.SetLastName("Wild"); chris.SetAge(51); chris.SetSSN("000-00-0000"); chris.SetGPA(4.0); chris.SetMajor("Computer Science"); cout << "after setting Chris:\n" << chris << endl << endl;
Student pam; cin >> pam; // have fun with input cout << "value of pam:\n" << pam << endl; }
(Complete Source Code Here)