advanced class features: - abstract data type (adt) -object oriented design (ood)
Post on 02-Jan-2016
22 Views
Preview:
DESCRIPTION
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 Features 2
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 Features 3
Conventional way of adding 2 fractionsvoid 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” functionprint(fr1); cout << " + "; print(fr2);cout << " = ";
// calling the “add” functionadd(fr1, fr2); print(fr1);cout << "\n";
}
COMP103 - Adv. Class Features 4
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 Features 5
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 Features 6
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 Features 7
Object Oriented Design
a Value:
Numerator = 1Denominator = 2
b Value:
Numerator = 2Denominator = 3
Class FractPublic 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 Features 8
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 Features 9
Implement as C++ Class
Class definition
Class Fract { private:
int numerator;int denominator;
public: Fract();Fract(int n, int d);
Fract(Fract ©From); //Copy Constructorvoid get(); // Read in from cinvoid print(); void increment(void); // Increment by 1 void addTo(Fract &f2);
};
private: user never needsto access this data directly!
COMP103 - Adv. Class Features 10
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 ConstructorFract::Fract(Fract ©From){
numerator = copyFrom.numerator; denominator = copyFrom.denominator;}
COMP103 - Adv. Class Features 11
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 Features 12
class array{
private:
int array_size;
int *array_data;
public:
array(); // default constructor
// copy constructor: value 0bit-wise; 1logical
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
s2s1
s2s1
s1 makes its own“copy” of the data
s1 points to s2’sdata
Case where copy constructor isimportant: Classes that have dynamicmemory
COMP103 - Adv. Class Features 13
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 Features 14
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 Features 15
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 isnot very intuitive. . not easy to use . .
COMP103 - Adv. Class Features 16
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 Features 17
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 Features 18
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 Features 19
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 Features 20
Friend FunctionsFriend 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 friendclass 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 Features 21
Overloading
Overloading - Definition of two or more functions or operators with the same identifier (name)
C++ allows two types of overloading: Function Overloading Operator Overloading
COMP103 - Adv. Class Features 22
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’ typesswap(a,b); swap(i,j); swap(q,p);
}
COMP103 - Adv. Class Features 23
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 Features 24
Operator Overloading
Recall:class Fract{
. . .
void increment(void);
void addTo(Fract &fr2);
friend Fract addFr(Fract &f1, Fract &f2);
};
Operation Function Syntax Arithmetic Syntax
Increment:
fr1 = fr1+1
fr1.increment(); ++fr1;
Add to:
fr1 = fr1 + fr2
fr1.addTo(f2); fr1 += fr2;
Add:
fr3 = fr1 + fr2
addFr(f1,f2); f1 + f2;
COMP103 - Adv. Class Features 25
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 Features 26
Operator Overloadingclass 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 Features 27
Overloading the Copy operator “ = “ Can write your own logical copy operator (Same as
copy constructor)class array { . . . void operator=(array &A);};// Logical Copy operatorvoid array::operator=(array &A){. . . // (see slide 12)
}void main(){Array A1, A2;
. . . A2 = A1; // performs the logical copy!!}
COMP103 - Adv. Class Features 28
Dynamic memory and classes You can dynamically allocate a class
object Use a pointer to a class (p.564), e.g.
// default-constructorFract *pf1 = new Fract;// explicit-value contructorFract *pf2 = new Fract(1,2);
Use member operator (.) (*pf1).get(); (*pf1).print();
Or use selection operator (->)pf1->get(); pf1->print();
COMP103 - Adv. Class Features 29
Deletion of Dynamic Objects Deletion and destructors Recall the special destructor function: ~<ClassName>()
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
top related