250 likes | 263 Views
CS 132 Spring 2008 Chapter 2. Object-Oriented Design (OOD) and C++ Ideas: * Inheritance (and protected members of a class) ** Operator overloading Pointer this * Operator overloading with friends ** Templates. Three Basic Principles of OOD. Encapsulation
E N D
CS 132 Spring 2008Chapter 2 Object-Oriented Design (OOD) and C++ Ideas: * Inheritance (and protected members of a class) ** Operator overloading Pointer this * Operator overloading with friends ** Templates
Three Basic Principles of OOD Encapsulation • combining data and operations into a single unit • where have we done this? Inheritance • ability to create new data types from existing ones Polymorphism • using the same expression to denote different meanings, e.g., overloading, overriding • where have we done this?
Inheritance person student faculty USresident • Derive student from person: • public members (e.g. setName) in person can be used in student • student has additional members (gpa in private, setGPA in public) • Multiple inheritance (we won't cover): faculty and USresident
class personType { public: void print() const; void setName(string first, string last); void getName(string& first, string& last); personType(string first = "", string last = ""); private: string firstName; string lastName; }; class studentType: public personType { public: void setStudent(string first, string last, int gpa); void setGPA(int gpa); float getGPA(); studentType(string first = "", string last = "", int gpa = 0); private: int GPA; }; person → student public members of personType are public in studentType: studentType student; student.setName("Fred", "Fink") //works
class personType { public: void print() const; void setName(string first, string last); void getName(string& first, string& last); personType(string first = "", string last = ""); private: string firstName; string lastName; }; class studentType: private personType { public: void setStudent(string first, string last, int gpa); void setGPA(int gpa); float getGPA(); studentType(string first = "", string last = "", int gpa = 0); private: int GPA; }; person → student different public members of personType are not public in studentType: studentType student; student.setName("Fred", "Fink") //does not work
Protected Members of a Class Problem: members of studentType cannot access firstName and lastName because they are private in personType If derived class needs access to members of the base class the members of base class are “protected” E.g. change "private" to "protected" in the parent class
class personType { public: void print() const; void setName(string first, string last); void getName(string& first, string& last); personType(string first = "", string last = ""); protected: string firstName; string lastName; }; class studentType: public personType { public: void setStudent(string first, string last, int gpa); void setGPA(int gpa); float getGPA(); studentType(string first = "", string last = "", int gpa = 0); private: int GPA; }; person → student different private members of personType can be used in studentType implementation See person2.h
Inheritance In person.h: public: void print() const; In student.h class studentType: public personType //public members of person can be used in derived class instances e.g. studentType aStudent; aStudent.print(); In student.h class studentType: private personType //person public members can be used only to implement derived class //but not on objects of that type e.g. studentType aStudent; aStudent.print(); //NOT ALLOWED Rarely used Example: a derived class patientType where you don't want to reveal patient names personp.h
Inheritance In person.h: protected: string firstName; //visible to derived classes string lastName; //visible to derived classes private: string firstName; //not visible to anyone except personTypeImp
Redefining Base Class Members print() defined in personType does not print the GPA Definition in studentType overrides print in personType studentTypeImp.cpp illustrates • redefinition • accessing protected members of personType (allowed because they are protected) • using the inherited function for print in studentType Pitfall: • constructors must be redefined
Inheritance Summary Public members of the base class • inherited by the derived class • can be directly accessed anyone Private members of base class • private to base class • cannot be directly accessed by anyone Protected members of base class • can be directly accessed only by derived class Derived class can redefine member functions of base class • redefined function must have the same name and parameters • redefinition applies only to objects of the derived class • if the same name is used with different parameters, it is different
Preprocessor Commands (p. 78) //Header file person.h #ifndef H_person #define H_person ... the contents of personType.h #endif #ifndef H_personmeans “if not defined H_person” #define H_personmeans “define H_person” #endif means “end if” This prevents compiling a file twice Not required in Visual C++ See person2c.h
Composition (p. 80) Another (easier) way to relate two classes A member of a class in an object of another class type Analogous to records having other records as components • e.g. a person has a birthday • “has-a” relation between classes E.g.: class personalInfoType {... private: personType person; dateType bDay; int personID; };
Confusing section: Pointer this Pointer: • a variable that contains an address of another variable • when you declare a variable, its name and type is stored in a symbol table along with a pointer to the address of the variable • later: pointer types that will be an important way to implement dynamic data structures Every object of a class maintains a (hidden) pointer to itself called “this” (a reserved word) When the object invokes a member function, the member function references the pointer "this" of the object
Pointer this Example on p. 90 (personImp.cpp): // & means the object using the method is by reference // *this is the object that is modified personType& personType::setFirstName(string first) { firstName = first; return *this; } Better (personImpv.cpp): //the method operates directly on the object void personType::setFirstName(string first) { firstName = first; } Both are called via aPerson.setFirstName("Fred");
Polymorphism: Operator Overloading Recall how clumsy printing and addition are for complexType: num1.print(); num3 = num1.add(num2); Nicer: cout << num1; num3 = num1 + num2; Operator function: overloads an operator Syntax of the heading of an operator function: returnType operator operatorSymbol (arguments) e.g. complexType operator+(const complexType& otherComplex) const; See example files
Overloading + In driver (testComplex.cpp): num3 = num1.add(num2); // add is applied to object num1 with parameter num2 num3 = num1 + num2; // + is applied to object num1 with parameter num2 In complexType.h: complexType add(const complexType& otherComplex) const; complexType operator+(const complexType& otherComplex) const; Implementation in complexType.cpp (both the same!): complexType temp; temp.realPart = realPart + otherComplex.realPart; temp.imaginaryPart = imaginaryPart + oherComplex.imaginaryPart; return temp;
Overloading the Stream Insertion Operator (<<) Let's try this with: cout << aComplex object operator parameter But cout is ostream, not personType We need a friend: • a nonmember function with access to private data members To make function a friend to a class, reserved word friend precedes prototype friend appears only in prototype, not in the function definition
Overloading << Function prototype (included in the class): friend ostream& operator<<(ostream&, const complexType&); Function definition: ostream&operator<<(ostream&osObject, constcomplexType& complex) { osObject<<complex.realPart; osObject<<" + "; osObject<<complex.imaginaryPart; osObject<<"i"; return osObject; //pointer this format } text example displays data in (a,b) format. How would this differ? osObject<< "(" << complex.realPart << ", " << complex.imaginaryPart << ")";
Overloading >> in (a,b) format Earlier program: user entered a and b separately. What if the number is in (a,b) format? a. Read and discard left parenthesis ( b. Read and store the real part a c. Read and discard the comma , d. Read and store the imaginary part b e. Read and discard the right parenthesis )
Overloading >> Function Prototype (included in the definition of the class): friend istream& operator>>(istream&, className&); Function Definition: istream& operator>>(istream& isObject, complexType& object) { char ch; isObject>>ch; isObject>>complex.realPart; isObject>>ch; isObject>>complex.imaginaryPart; isObject>>ch; return isObject; }no const since the object will change
Bad News Example programs do not compile • Change #include <iostream> to #include <iostream.h> • Remove using namespace std Why? A peculiarity of Visual C++
Overloading Unary Operators Unary operators: one argument E.g. a++ (unary) versus a + b (binary) The second argument was a parameter in the overloaded definition complexType operator+(const complexType& otherComplex) const; cComplex = aComplex + bComplex the object the parameter But there is no second argument: dateType operator++(); //get the next day aDate++; the object the operator
Templates Powerful C++ tools Use a function template to write a single code segment for a set of related functions that may operate on different types (E.G. max, last semester) Use a class template for classes that may have similar functionality on different data types Example: • listType • we will use this in the next program to review arrays
Syntax Syntax for a function template: template<class Type> //Type is the parameter function definition; Syntax for a class template: template<class Type> class declaration New rule • the class header and implementation must be compiled together Options • put them both in the same file (what we will do) • put an include for the .cpp at the end of the header