CS 132 Spring 2008 Chapter 2 ObjectOriented Design
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 – 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. set. Name) in person can be used in student has additional members (gpa in private, set. GPA in public) Multiple inheritance (we won't cover): faculty and USresident
person → student class person. Type { public: void print() const; void set. Name(string first, string last); void get. Name(string& first, string& last); person. Type(string first = "", string last = ""); private: string first. Name; string last. Name; }; class student. Type: public person. Type { public: void set. Student(string first, string last, int gpa); void set. GPA(int gpa); float get. GPA(); student. Type(string first = "", string last = "", int gpa = 0); private: int GPA; }; public members of person. Type are public in student. Type: student. Type student; student. set. Name("Fred", "Fink") //works
person → student different class person. Type { public: void print() const; void set. Name(string first, string last); void get. Name(string& first, string& last); person. Type(string first = "", string last = ""); private: string first. Name; string last. Name; }; class student. Type: private person. Type { public: void set. Student(string first, string last, int gpa); void set. GPA(int gpa); float get. GPA(); student. Type(string first = "", string last = "", int gpa = 0); private: int GPA; }; public members of person. Type are not public in student. Type: student. Type student; student. set. Name("Fred", "Fink") //does not work
Protected Members of a Class Problem: members of student. Type cannot access first. Name and last. Name because they are private in person. Type 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
person → student class person. Type { public: void print() const; void set. Name(string first, string last); void get. Name(string& first, string& last); person. Type(string first = "", different string last = ""); protected: string first. Name; string last. Name; }; class student. Type: public person. Type { public: void set. Student(string first, string last, int gpa); void set. GPA(int gpa); float get. GPA(); student. Type(string first = "", string last = "", int gpa = 0); private: int GPA; }; private members of person. Type can be used in student. Type implementation See person 2. h
Inheritance In person. h: public: void print() const; In student. h class student. Type: public person. Type //public members of person can be used in derived class instances e. g. student. Type a. Student; a. Student. print(); In student. h class student. Type: private person. Type //person public members can be used only to implement derived class //but not on objects of that type e. g. student. Type a. Student; a. Student. print(); //NOT ALLOWED Rarely used Example: a derived class patient. Type where you don't want to reveal patient names personp. h
Inheritance In person. h: protected: string first. Name; //visible to derived classes string last. Name; //visible to derived classes private: string first. Name; //not visible to anyone except person. Type. Imp
Redefining Base Class Members print() defined in person. Type does not print the GPA Definition in student. Type overrides print in person. Type student. Type. Imp. cpp illustrates – redefinition – accessing protected members of person. Type (allowed because they are protected) – using the inherited function for print in student. Type 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 person. Type. h #endif #ifndef H_person means “if not defined H_person” #define H_person means “define H_person” #endif means “end if” This prevents compiling a file twice Not required in Visual C++ See person 2 c. 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 personal. Info. Type {. . . private: person. Type person; date. Type b. Day; int person. ID; };
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 (person. Imp. cpp): // & means the object using the method is by reference // *this is the object that is modified person. Type& person. Type: : set. First. Name(string first) { first. Name = first; return *this; } Better (person. Impv. cpp): //the method operates directly on the object void person. Type: : set. First. Name(string first) { first. Name = first; } Both are called via a. Person. set. First. Name("Fred");
Polymorphism: Operator Overloading Recall how clumsy printing and addition are for complex. Type: num 1. print(); num 3 = num 1. add(num 2); Nicer: cout << num 1; num 3 = num 1 + num 2; Operator function: overloads an operator Syntax of the heading of an operator function: return. Type operator. Symbol (arguments) e. g. complex. Type operator+(const complex. Type& other. Complex) const; See example files
Overloading + In driver (test. Complex. cpp): num 3 = num 1. add(num 2); // add is applied to object num 1 with parameter num 2 num 3 = num 1 + num 2; // + is applied to object num 1 with parameter num 2 In complex. Type. h: complex. Type add(const complex. Type& other. Complex) const; complex. Type operator+(const complex. Type& other. Complex) const; Implementation in complex. Type. cpp (both the same!): complex. Type temp; temp. real. Part = real. Part + other. Complex. real. Part; temp. imaginary. Part = imaginary. Part + oher. Complex. imaginary. Part; return temp;
Overloading the Stream Insertion Operator (<<) Let's try this with: cout << a. Complex object operator parameter But cout is ostream, not person. Type 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 complex. Type&); Function definition: ostream& operator<<(ostream& os. Object, const complex. Type& complex) { os. Object<<complex. real. Part; os. Object<<" + "; os. Object<<complex. imaginary. Part; os. Object<<"i"; return os. Object; //pointer this format } text example displays data in (a, b) format. How would this differ? os. Object<< "(" << complex. real. Part << ", " << complex. imaginary. Part << ")";
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 c. Read and discard the comma d. Read and store the imaginary part e. Read and discard the right parenthesis ( a , b )
Overloading >> Function Prototype (included in the definition of the class): friend istream& operator>>(istream&, class. Name&); Function Definition: istream& operator>>(istream& is. Object, complex. Type& object) { char ch; is. Object>>complex. real. Part; is. Object>>ch; is. Object>>complex. imaginary. Part; is. Object>>ch; return is. Object; } no const since the object will change
Bad News Example programs do not compile 1. Change #include <iostream> to #include <iostream. h> 2. 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 complex. Type operator+(const complex. Type& other. Complex) const; c. Complex = a. Complex + b. Complex the object the parameter But there is no second argument: date. Type operator++(); a. Date++; the object the operator //get the next day
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: – list. Type – we will use this in the next program to review arrays
Syntax for a function template: template<class Type> function definition; //Type is the parameter 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
- Slides: 25