# This set of notes is adapted from that provided by “Computer Science – A Structured Programming Approach Using C++”, B.A. Forouzan & R.F. Gilberg, Thomson.

## Presentation on theme: "This set of notes is adapted from that provided by “Computer Science – A Structured Programming Approach Using C++”, B.A. Forouzan & R.F. Gilberg, Thomson."— Presentation transcript:

This set of notes is adapted from that provided by “Computer Science – A Structured Programming Approach Using C++”, B.A. Forouzan & R.F. Gilberg, Thomson Learning, 2000. Advanced Class Features: - Abstract Data Type (ADT) -Object Oriented Design (OOD) Chapters 11

COMP103 - Adv. Class Features2 Conventional way of adding 2 fractions Declare fraction, “ fract ” as struct type: struct Fract { int numerator; int denominator; }; Define functions “ add ” and “ print ” : void add(Fract &f1, Fract f2) { f1.numerator = f1.numerator*f2.denominator + f2.numerator*f1.denominator; f1.denominator = f1.denominator*f2.denominator; return; } // add: f1 = f1 + f2; void print (Fract f) { cout << f.numerator << "/" << f.denominator; }

COMP103 - Adv. Class Features3 Conventional way of adding 2 fractions void main(){ // Local Declarations - conventional Fract fr1, fr2; // Assigning values to fr1 and fr2 fr1.numerator = 1; fr1.denominator = 3; fr2.numerator = 2; fr2.denominator = 5; cout << "Fract: "; // calling the “print” function print(fr1); cout << " + "; print(fr2); cout << " = "; // calling the “add” function add(fr1, fr2); print(fr1); cout << "\n"; }

COMP103 - Adv. Class Features4 Conventional way of adding 2 fractions Note: users need to know the field names, i.e., fr1.numerator and fr1.denominator how to initialize the fractions, e.g. fr1.numerator=1; where put the target fraction fr1 as the first parameter in add(fr1, fr2) that the first parameter should be passed by reference,i.e., void add(Fract &f1, Fract f2) These are implementation details of Fraction. One should not bother the users with these details. Users should only be concerned of what a “Fraction object” can do but not how it accomplishes its task.  Use Abstract Data Type also referred to as Object Oriented Design

COMP103 - Adv. Class Features5 Using “ADT” (or “OOD”) The main program becomes: void main() { // Local Declaration using ADT (class type) // assign values - constructors Fract f1(1,3), f2(2, 5); cout << "Fraction: "; // class member function “print” f1.print(); cout << " + "; f2.print(); cout << " = "; // class member function “add” f1.add(f2); f1.print(); cout << "\n"; }

COMP103 - Adv. Class Features6 Abstract Data Type (ADT) When we implement an “object” as an ADT (Abstract Data Type), We hide the implementation details from the users This is facilitated by using CLASS type in C++ Data fields should be declared as private What the object can do is provided as public functions (methods)

COMP103 - Adv. Class Features7 Object Oriented Design a Value: Numerator = 1 Denominator = 2 b Value: Numerator = 2 Denominator = 3 Class Fract Public functions: Add(), Subtract(), Multiply(),Divide(), Equal(), LessThan(), Print(), Get() Private Data members: Numerator, Denominator Fract a(1,2); Fract b(2,3); (object 1) (object 2)

COMP103 - Adv. Class Features8 Case Study: “Fract” Class Design a simple abstract data type (ADT): Fract Data (private): numerator, denominator Operations (things you can do with fractions) initialize [ Constructors ] read print copy increment fraction (add +1) add to another fraction // f1 = f1 + f2 add two fractions // f3 = f1 + f2

COMP103 - Adv. Class Features9 Implement as C++ Class Class definition Class Fract { private: int numerator; int denominator; public: Fract(); Fract(int n, int d); Fract(Fract ©From);//Copy Constructor void get();// Read in from cin void print(); void increment(void);// Increment by 1 void addTo(Fract &f2); }; private: user never needs to access this data directly!

COMP103 - Adv. Class Features10 Constructors (3 Types) // Default Constructor: Fract=1/1; Fract::Fract() { numerator = 1; denominator = 1; } // Explicit value Constructor: Fract=n/d; Fract::Fract(int n, int d) { numerator = n; denominator = d; } // Bit-wise Copy Constructor Fract::Fract(Fract ©From) { numerator = copyFrom.numerator; denominator = copyFrom.denominator; }

COMP103 - Adv. Class Features11 Copy Constructor Copy Constructor is a special constructor It is called in the following situation Fract fr2(fr1); // fr2 = fr1; Copy Constructor Syntax ClassName::ClassName(ClassName &var) Examples: MyString::MyString(MyString &s) Fract::Fract(Fract &f) Complex::Complex(Complex &c) array::array(array &A) // recall: Constructors.cpp

COMP103 - Adv. Class Features12 class array{ private: int array_size; int *array_data; public: array(); // default constructor // copy constructor: value 0  bit-wise; 1  logical array(array &A, int value);... }; // Constructors.cpp (24 March Notes) Array::array(array &A, int value){ array_size = A.size(); switch(value) { case 0: // Bitwise Copy array_data = A.array_data; break; case 1: // Logical Copy array_data = new int[array_size]; for (int i=0; i < array_size; i++) array_data[i] = A.array_data[i]; break; } Bitwise vs. Logical Copy Constructor size data size data size data size data Bitwise (copy s2 to s1) Logical Copy Constructor s2 s1 s2 s1 s1 makes its own “copy” of the data s1 points to s2’s data Case where copy constructor is important: Classes that have dynamic memory

COMP103 - Adv. Class Features13 Functions: “get” and “print” void Fract::get() { cout << “ Input Fraction (n d): “; cin >> numerator >> denominator; } void Fract::print() { if (denominator == 0) // n/0 is infinity cout << “Infinity\”; else cout << numerator << “/” << denominator; }

COMP103 - Adv. Class Features14 Functions: “increment” and “addTo(...)” // increment: f1 = f1 + 1  a/b + 1 = (a+b)/b void Fract::increment() // Add one to fraction { numerator += denominator; } // addTo: f1 = f1 + f2  a/b + c/d = (a*d + c*b)/b*d void Fract::addTo(Fraction &f2) { numerator = numerator*f2.denominator + f2.numerator*denominator; denominator = denominator*f2.denominator; }

COMP103 - Adv. Class Features15 We want: f3 = f2 + f1 (how?) void main() { // declare and initialize f1 and f2 Fract f1(1,2), f2(1,2); // copy f1 to f3 Fract f3(f1); // add f2 to f3,i.e., f3 = f3 + f2 f3.addTo(f2); } This addTo(...) method is not very intuitive.. not easy to use..

COMP103 - Adv. Class Features16 Another function: addFr(...) Class Fract { private: int numerator; int denominator; public: Fract(); Fract(int n, int d); Fract(Fract ©From);//Copy Constructor void get();// Read in from cin void print(); void increment();// f1 = f1 + 1; void addTo(Fract &f2); // f1 = f1 + f2; Fract addFr(Fract &f1, Fract &f2); };

COMP103 - Adv. Class Features17 Member Function addFr(...) Remember we want f3 = f2 + f1 addFr(...), as a member function of class Fract, must be called by an object! void main() { // declare and initialize f1 and f2 Fract f1(1,2), f2(1,2), f3; // member function can only be called by an object f3 = f1.addFr(f1,f2); } Note, we can also achieve the same result by: f3 = f2.addFr(f1,f2); or f3 = f3.addFr(f1,f2); Awkward usage!! We want f3 = f1 + f2!

COMP103 - Adv. Class Features18 Solution: addFr(...) as an external function Fract addFr(Fract &f1, const Fract &f2) { Fract tempFr; tempFr.numerator = f1.numerator*f2.denominator + f2.numerator*f1.denominator; tempFr.denominator = f1.denominator*f2.denominator; return (tempFr); } Void main() { Fract f1(1,2), f2(1,2), f3; f3 = addFr(f1,f2); } This is what we want - But, addFr() cannot access Fract’s private data! We could make Fract’s data public - This violates ADT design - Allows user unnecessary access

COMP103 - Adv. Class Features19 Another Solution: Friend Functions C++ has a way to allow non-member function to access private variables: friend functions class Fract { private:... public:... friend Fract addFr(Fract &f1, Fract &f2); }; Fract addFr(Fract &f1, Fract &f2) // Notice no scope { // operator (::)... }

COMP103 - Adv. Class Features20 Friend Functions Are not members of a class They are associated with the class and given special privileges Allow to access private members data and functions To declare an external function as a friend function: prefix its prototype with the keyword friend class MyClass{... friend void doSomething1(MyClass c1,... ); friend int doSomething2(Myclass c1,... ); friend MyClass doSomething3(...); friend OtherClass; // A friend can actually be another class! // (We’ll re-visit this with linked-list) };

COMP103 - Adv. Class Features22 C++ Function Overloading Example: “swap” void swap(char &, char &); void swap(int &, int &); void swap(float &, float &); void main() { char a=‘x’, b=‘y’; int i=10, j=-10; float q=1.34, p=3.14; // compiler knows which one to call // by examining the parameters’ types swap(a,b); swap(i,j); swap(q,p); }

COMP103 - Adv. Class Features23 Function Overloading Compiler uses only the parameters (not the return type) to detect overloading float *average(int *array); int *average (int *array); These will not be considered overloaded and will cause a compiler error! not overloaded

COMP103 - Adv. Class Features25 Operator Overloading C++ allows us to overload the operators for a more natural coding style class Fract { private: int numerator; int denominator; public:... void operator++(); // increment: ++fr1 } void Fract::operator++() { numerator += denominator; }

COMP103 - Adv. Class Features26 Operator Overloading class Fract { private: int numerator; int denominator; public:... void operator++(); void operator+=(Fract &fr2); friend Fract operator+(Fract &f1, Fract &f2 ); } void Fract::operator++() { // same as increment – fr1 = fr1 + 1 } void Fract::opeartor+=(Fract &fr2) { // same as addTo – fr1 = fr1 + fr2 } Fract operator+(Fract &fr1, Fract &fr2) { // same as addFr – fr3 = fr1 + fr2 }

COMP103 - Adv. Class Features27 Overloading the Copy operator “ = “ Can write your own logical copy operator (Same as copy constructor) class array {... void operator=(array &A); }; // Logical Copy operator void array::operator=(array &A) {... // (see slide 12) } void main(){ Array A1, A2;... A2 = A1; // performs the logical copy!! }

COMP103 - Adv. Class Features28 Dynamic memory and classes You can dynamically allocate a class object Use a pointer to a class (p.564), e.g. // default-constructor Fract *pf1 = new Fract; // explicit-value contructor Fract *pf2 = new Fract(1,2); Use member operator (.) (*pf1).get();(*pf1).print(); Or use selection operator (->) pf1->get();pf1->print();

COMP103 - Adv. Class Features29 Deletion of Dynamic Objects Deletion and destructors Recall the special destructor function: ~ () The “delete” keyword used to free dynamic memory will call the destructor of an object Fract *pf1 = new Fract(1,2); pf1->print(); // or (*pf1).print(); delete pf1; // pf1’s destructor will be called

COMP103 - Adv. Class Features30 Summary More C++ and C++ Class Functionality Fract Case Study Copy Constructor Bitwise vs. Logical Copy Friend Functions Function Overloading Operator Overloading Dynamically Allocated Objects, Pointers to Objects Fract *pf = new Fract(1,2);

Download ppt "This set of notes is adapted from that provided by “Computer Science – A Structured Programming Approach Using C++”, B.A. Forouzan & R.F. Gilberg, Thomson."

Similar presentations