Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 11 Friends and Overloaded Operators. Introduction to function equal // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate();

Similar presentations


Presentation on theme: "Chapter 11 Friends and Overloaded Operators. Introduction to function equal // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate();"— Presentation transcript:

1 Chapter 11 Friends and Overloaded Operators

2 Introduction to function equal // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor CDate(const CDate& aDay); // copying constructor ~CDate(); // destructor int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int year; private: int month; int day; }; #endif #include “Date.h” bool equal (CDate day1, CDate day2); void main () { CDate myBD(3, 31, 1996), yourBD; cout << "Enter your birthday as month, day, year ”; int m, d; cin >> m >> d >> yourBD.year; yourBD.setMonth(m); yourBD.setDay(d); if (equal(myBD, yourBD)) cout << “Let’s celebrate together.”; } bool equal (CDate day1, CDate day2) { return (day1.getMonth() == day2.getMonth()) && day1. getDay() == day2. getDay()) && day1.year == day2.year); }

3 Function equal prototype of equal is outside of the class. equal is a nonmember function of the class requiring 2 objects To access the members, it must still use member accessor functions since the attributes are private and can only be accessed by public member functions. It does not change the data members. Only member functions or friend functions should be able to alter private members.

4 Friend functions A non-member function that has membership privileges. Notes: – Prototype goes in public section with keyword friend in front – Function call is like a regular function - does not use dot operator – When to use: Functions between two members of the same class

5 Friend function equal // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor CDate(const CDate& aDay); // copying constructor ~CDate(); // destructor friend bool equal(CDate day1, CDate day2); int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int year; private: int month; int day; }; #endif #include “Date.h” void main () { CDate myBD(3, 31, 1996), yourBD; cout << "Enter your birthday as month, day, year ”; int m, d; cin >> m >> d >> yourBD.year; yourBD.setMonth(m); yourBD.setDay(d); if (equal(myBD, yourBD)) cout << “Let’s celebrate together.”; } bool equal (CDate day1, CDate day2) { return (day1.month == day2.month) && day1. day == day2. day) && day1.year == day2.year); }

6 The const Parameter Modifier It is more efficient to call by reference than by value. – value: passes in a copy of the variable. If the variable is large or structured this takes up extra space. – reference: passes in the address only but it does allow changes Solution: call by reference but put const modifier which prevents change - generates error message. Used for classes, structs and arrays. const used after function prototype and definition prevents function from changing calling objects - generates error message. – void output (ostream& outs) const; If the function prototype and it’s definition do not both have the const modifier, then you will get a linkage error. Accessor and output functions should be const.

7 Friend function equal with const // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor CDate(const CDate& aDay); // copying constructor ~CDate(); // destructor friend bool equal(const CDate& day1, const CDate& day2); int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int year; private: int month; int day; }; #endif #include “Date.h” void main () { CDate myBD(3, 31, 1996), yourBD; cout << "Enter your birthday as month, day, year ”; int m, d; cin >> m >> d >> yourBD.year; yourBD.setMonth(m); yourBD.setDay(d); if (equal(myBD, yourBD)) cout << “Let’s celebrate together.”; } bool equal (const CDate& day1, const CDate& day2) { return (day1.month == day2.month) && day1. day == day2. day) && day1.year == day2.year); }

8 Overloading Operator Changing the definition of an operator from the default operation to a new operation. Allows for smooth functionality in ADT’s.

9 Overloading Operator (example) Want to write as: if (myBD == yourBD) // syntax error Current operation == does not take operands typed CDate. Need to redefine == operator to take 2 CDate objects. Function definition is exactly the same as equal. Declared as a friend function. Has the keyword operator.

10 Friend function equal with const // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor CDate(const CDate& aDay); // copying constructor ~CDate(); // destructor friend bool operator ==(const CDate& day1, const CDate& day2); int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int year; private: int month; int day; }; #endif #include “Date.h” void main () { CDate myBD(3, 31, 1996), yourBD; cout << "Enter your birthday as month, day, year ”; int m, d; cin >> m >> d >> yourBD.year; yourBD.setMonth(m); yourBD.setDay(d); if (myBD == yourBD) cout << “Let’s celebrate together.”; } bool operator ==(const CDate& day1, const CDate& day2) { return (day1.month == day2.month) && day1. day == day2. day) && day1.year == day2.year); }

11 Rules for Overloading Operators At least one argument must be of the class type. Overloaded operators can be friends or member functions. Can only overload existing operators Can’t change the number of arguments from the original operator (binary (+), unary (++)) Can’t change precedence rules Can’t overload dot operator(.), scope resolution operator (::). Overloading the assignment operator is a special case.

12 Overloading Unary Operators Has only 1 object in the parameter list: – Negate: - – Increment: ++ – Decrement: --

13 Overloading >> and << The compiler does not automatically know how to output or input user-defined classes. Need to specify how each attribute is to be entered. Want input to be user friendly. – Ex: cin >> yourBD; // as format mm-dd-yyyy Want output to be clear and in standard form. – Ex: cout << yourBD; // as format mm/dd/yyyy

14 Arrays and Classes An array can be of any type. Composite types (struct or class) can be stored in arrays. Ex: CDate studentBDs[25]; int n=5; if (studentBDs[n] == myBD) if (studentBDs[n].year < 1998) if (studentBDs[n].getMonth() == 3)

15 Arrays as Class Member Any composite type can contain an array. Ex class CStudentInfo { … char name; SDate bDay; float quiz[5]; }; CStudentInfo students[25], myBestStudent; myBestStudent.quiz[0] = 10; students[2].quiz[0] = 8;

16 Class CComplex definition //Complex.h #ifndef _COMPLEX_ #define _COMPLEX_ #include using namespace std; class CComplex { public: CComplex(void); CComplex(double, double); CComplex(const CComplex&); ~CComplex(); // Unary operator to negate the values of a complex number: // -(r, i) = (-r, -i) friend CComplex operator - (const CComplex& c); // operator to add 2 complex numbers: // (r1, i1) + (r2, i2) = (r1+r2, i1+i2) friend CComplex operator + (const CComplex& left, const CComplex& right); // operator to subtract 2 complex numbers: // (r1, i1) - (r2, i2) = (r1-r2, i1-i2) friend CComplex operator - (const CComplex& left, const CComplex& right); // operator to multiply 2 complex numbers: // (r1, i1)(r2, i2) = (r1r2-i1i2, i1r2+r1i2) friend CComplex operator * (const CComplex& left, const CComplex& right); // operator to compare if 2 complex numbers are the same friend bool operator == (const CComplex& left, const CComplex& right); // extraction operator to get input for real, imaginary friend istream& operator >> (istream& ins, CComplex& c); // insertion operator to display a complex number as (a + bi) // where a is real and b is imag friend ostream& operator << (ostream& outs, const CComplex& c); private: double real; double imag; }; #endif

17 Class CComplex implementation CComplex::CComplex(void) : real(0), imag(0) {} CComplex::CComplex(double r, double i) : real(r), imag(i) {} CComplex::CComplex(const CComplex& c) real(c.real), imag(c.imag) {} CComplex::~CComplex() {} CComplex operator - (const CComplex& c) { CComplex temp; temp.real = -c.real; temp.imag = -c..imag; return temp; } CComplex operator + (const CComplex& left, const CComplex& right) { CComplex temp; temp.real = left.real + right.real; temp.imag = left.imag + right.imag; return temp; } CComplex operator - (const CComplex& left, const CComplex& right) { CComplex temp; temp.real = left.real - right.real; temp.imag = left.imag - right.imag; return temp; } CComplex operator * (const CComplex& left, const CComplex& right) { CComplex temp; temp.real = left.real*right.real - left.imag*right.imag; temp.imag = left.imag*right.real + left.real*right.imag; return temp; } bool operator == (const CComplex& left, const CComplex& right) { return (left.real == right.real) && (left.imag == right.imag); } istream& operator >> (istream& ins, CComplex& c) { ins >> c.real >> c.imag; return ins; } ostream& operator << (ostream& outs, const CComplex& c) { outs.setf(ios::fixed); outs.setf(ios::showpoint); outs.precision(2); outs << '(' << c.real << ", "; if (c.imag > 0.0) outs << '+'; outs << c.imag << “i)”; return outs; }

18 Class CComplex implementation (used parameterized constructor) CComplex::CComplex(void) : real(0), imag(0) {} CComplex::CComplex(double r, double i) : real(r), imag(i) {} CComplex::CComplex(const CComplex& c) real(c.real), imag(c.imag) {} CComplex::~CComplex() {} CComplex operator - (const CComplex& c) { return CComplex(-c.real, -c.imag); } CComplex operator + (const CComplex& left, const CComplex& right) { return CComplex((left.real + right.real), (left.imag + right.imag)); } CComplex operator - (const CComplex& left, const CComplex& right) { return CComplex(left.real - right.real, left.imag - right.imag); } CComplex operator * (const CComplex& left, const CComplex& right) { return CComplex((left.real*right.real - left.imag*right.imag), (left.imag*right.real + left.real*right.imag)); } bool operator == (const CComplex& left, const CComplex& right) { return (left.real == right.real) && (left.imag == right.imag); } istream& operator >> (istream& ins, CComplex& c) { ins >> c.real >> c.imag; return ins; } ostream& operator << (ostream& outs, const CComplex& c) { outs.setf(ios::fixed); outs.setf(ios::showpoint); outs.precision(2); outs << '(' << c.real << ", "; if (c.imag > 0.0) outs << '+'; outs << c.imag << “i)”; return outs; }

19 Class with pointer data members #include "Date.h" CDate::Date () : month(1), day(1), year(new int(1900)) {} CDate::Date (int m, int d, int y) : month(1), day(1), year(new int(y)) {} CDate::~Date () {} int CDate::getMonth() { return month; } int CDate::getMonth() { return month; } int CDate::getDay() { return day; } void CDate::setMonth(int m) { month = m; } …. class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor ~CDate(); // destructor int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int *year; private: int month; int day; };

20 Destructor Every class needs to tell the compiler how to destroy the object and return the memory to the freestore. Destructor is used to destroy a class object and return the memory to the heap. – In the case of standard variables, it will automatically return the memory to the heap and the destructor is empty. – In the case of dynamic variables, it will destroy the pointer but not return the memory to the heap unless we use the delete command. With dynamic variables, only the pointer would be deleted and not what it points to. Need to write the destructor specifically and use delete. Automatically called when scope ends

21 Destructor (example) class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor ~CDate(); // destructor int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int *year; private: int month; int day; }; #include "Date.h" CDate::Date () : month(1), day(1), year(new int(1900)) {} CDate::Date (int m, int d, int y) : month(1), day(1), year(new int(y)) {} CDate::~Date () { cout <<“Bye-bye: ”<<month<<“-”<<day<<“-”<<*year<<endl; } … #include "Date.h“ void main () { CDate myBD (1, 1, 1990); CDate yourBD (12, 31, 2000); } Bye-bye: 12-31-2000 Bye-bye: 1-1-1990 Output: So, what happens to the memory location reserved for year? Still occupied

22 Destructor (example) class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor ~CDate(); // destructor int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int *year; private: int month; int day; }; #include "Date.h" CDate::Date () : month(1), day(1), year(new int(1900)) {} CDate::Date (int m, int d, int y) : month(1), day(1), year(new int(y)) {} CDate::~Date () { cout <<“Bye-bye: ”<<month<<“-”<<day<<“-”<<*year<<endl; delete year; } … #include "Date.h“ void main () { CDate myBD (1, 1, 1990); CDate yourBD (12, 31, 2000); } Bye-bye: 12-31-2000 Bye-bye: 1-1-1990 Output: So, what happens to the memory address reserved for year? Freed

23 Copy Constructor Creates a copy of an object in a different memory location. Parameter list has one variable that is an object of the class. The parameter is preceded by const and is a call by reference. – Ex: CDate (const CDate& d); Called automatically whenever a function has a parameter of the class type. – Ex: CDate myBD(yourBD); Any classes using pointers and new operator (dynamic variables) should have a copy constructor. Otherwise, the compiler will only copy the pointers so they both have the same address (both point to the same memory address, rather than each point to the same data but in different addresses. This is called a “shallow copy”).

24 Copy Constructor (example) #include "Date.h“ CDate::CDate () : month(1), day(1), year(new int(1900)) {} CDate::CDate (int m, int d, int y) : month(1), day(1), year(new int(y)) {} CDate::~CDate () { delete year; } CDate::CDate (const CDate& d) : month(d.month), day(d.day), year(d.year) {} CDate::~CDate () { delete year; } … class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor CDate(const CDate&); // copy constructor ~CDate(); // destructor int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int *year; private: int month; int day; };

25 Copy Constructor (const.) #include "Date.h“ void main () { CDate myBD (1, 1, 1990); { CDate yourBD (myBD); } cout << “My birth year is: ” << myBD.year << endl; } What happens to the memory address reserved for myBD’s year? Destroyed by yourBD’s destructor Output: ??? -17891602 (garbage) Why garbage??? myBD’s year yourBD’s year 1900 myBD’s year yourBD’s year ? Both myBD’s year and yourBD’s year point to the same memory address. When one is destroyed, the other becomes dangling pointer. 10,000

26 Copy Constructor (example) class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor CDate(const CDate&); // copy constructor ~CDate(); // destructor int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function int *year; private: int month; int day; }; #include "Date.h" CDate::CDate () : month(1), day(1), year(new int(1900)) {} CDate::CDate (int m, int d, int y) : month(1), day(1), year(new int(y)) {} CDate::~CDate () { delete year; } CDate::CDate (const CDate& d) : month(d.month), day(d.day) { year = new int; *year = *(d.year); } CDate::~CDate () { delete year; } …

27 Copy Constructor (const.) #include "Date.h“ void main () { CDate myBD (1, 1, 1990); { CDate yourBD (myBD); } cout << “My birth year is: ” << myBD.year << endl; } What happens to the memory address reserved for myBD’s year? Still there and used by myBD’s year Output: ??? 1990 Why exception NOT raised??? myBD’s year yourBD’s year 1900 myBD’s year yourBD’s year ? Both myBD’s year points to a different memory address, not related to the address of yourBD’s year. 10,000190011,000 190010,000

28 Overloading the Assignment Operator If NOT overloaded, the compiler will create one and that assignment operator will copy all the values of data members of the assigner (on the right) to the corresponding ones of the assignee (on the left). The “shallow copy” will happen if a data member is a pointer. So, the assignment operator needs to be overloaded to assign the pointer to another memory address. void CDate::operator = (const CDate& d) { month = d.month; day = d.day; year = d.year; }

29 Assignment Operator not overloaded #include "Date.h“ void main () { CDate myBD (1, 1, 1990); {CDate yourBD = myBD; } cout << “My birth year is: ” << myBD.year << endl; } What happens to the memory address reserved for myBD’s year? Destroyed by yourBD’s destructor Output: ??? -17891602 (garbage) Why garbage??? Both myBD’s year and yourBD’s year point to the same memory address. When one is destroyed, the other becomes dangling pointer. myBD’s year yourBD’s year 1900 myBD’s year yourBD’s year ? 10,000

30 Overloaded Assignment Operator (example) class CDate { public: CDate(); // default constructor CDate(int m, int d, int y); // parameterized constructor CDate(const CDate&); // copy constructors ~CDate(); // destructor int getMonth(); // accessor int getDay(); // accessor void setMonth(int m); // mutator void setDay(int d); // mutator void display(); // a member function void operator = (const CDate& d); // Assignment op. int *year; private: int month; int day; }; #include "Date.h" CDate::CDate () : month(1), day(1), year(new int(1900)) {} CDate::CDate (int m, int d, int y) : month(1), day(1), year(new int(y)) {} CDate::~CDate () { delete year; } CDate::CDate (const CDate& d) : month(d.month), day(d.day) { year = new int; *year = *(d.year); } CDate::~CDate () { delete year; } void CDate::operator = (const CDate& d) { month = d.month; day = d.day; year = new int; *year = *(d.year); } …

31 Overloaded Assignment Operator (const.) #include "Date.h“ void main () { CDate myBD (1, 1, 1990); { CDate yourBD (myBD); } cout << “My birth year is: ” << myBD.year << endl; } What happens to the memory address reserved for myBD’s year? Still there and used by myBD’s year Output: ??? 1990 Why exception NOT raised??? myBD’s year yourBD’s year 1900 myBD’s year yourBD’s year ? Both myBD’s year points to a different memory address, not related to the address of yourBD’s year. 10,000190011,000 190010,000

32 The Big Three Copy constructor, assignment operator and destructor are the big three of a class. Rule that if you need to define one of them, you need to define all of them or the compiler will create them but they might not work correctly!


Download ppt "Chapter 11 Friends and Overloaded Operators. Introduction to function equal // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate();"

Similar presentations


Ads by Google