Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 25

IEG 3080 Tutorial Three

Is-a and Has-a Relationship


Class Inheritance
Over-ridding
Access Control
Multiple Inheritance
Exception Handling
Assignment Two – Phase One
Prepared by Brian Lam Tak Cheung 1
Key Paradigm in OOP
Abstraction
intellectual simplification
Encapsulation
information hiding
Inheritance
reuse
Polymorphism
dynamic binding

Prepared by Brian Lam Tak Cheung 2


Is-a and Has-a Relationship

 In the last assignment, we know how to define our own object.


But there are still few interactions between different objects.

complex Vector Scalar

Through Operator Overloading


Work on its own

 Beside operator overloading, there are some closer


relationships between different objects.
We call them Is-a and Has-a Relationship.
Prepared by Brian Lam Tak Cheung 3
Is-a and Has-a Relationship
Examples of Is-a Relationship
Square is-a Rectangle Singer Actor
Rectangle is-a Shape
Triangle is-a Shape
Gigi is-a Actor
Gigi is-a Singer

Examples of Has-a Relationship


Rectangle has-a Edge
Square has-a Edge
Triangle has-a Edge
Gigi has-a boy friend ?!

Prepared by Brian Lam Tak Cheung 4


Is-a and Has-a Relationship
class Instructor {
private:
string name;
Tutor *tutor;
public:
Instructor();
Instructor(string name_in, Tutor t0, Tutor t1, Tutor t2);
void judge();
~Instructor();
};

Instructor::Instructor() Instructor::Instructor(string name_in, Tutor t0, Tutor t1, Tutor t2)


{ {
Tutor t0 = Tutor("A"); name = name_in;
Tutor t1 = Tutor("B",100); tutor = new Tutor[3];
Tutor t2 = Tutor("C",80); tutor[0] = t0;
Instructor("Wing Wong", t0, t1, t2); tutor[1] = t1;
}; tutor[2] = t2;
};

Prepared by Brian Lam Tak Cheung 5


Is-a and Has-a Relationship
class Singer {
private:
string name;
public:
Singer(string name_in);
void singTogether(Singer s);
~Singer();
};
Singer::Singer(string name_in)
{
name = name_in;
};

Signer:: singTogether(Singer s)
{
cout << name << “ : Do Re Me Fa So” << endl;
cout << s.name << “ : So Fa Me Re Do” << endl;
};

Prepared by Brian Lam Tak Cheung 6


Class Inheritance
Why need Class Inheritance?
Class reuse. Reuse all data and method from base class to create a
new derived class.

Syntax
Declaration of derived class
class derived_class_name : access_control_label base_class_name
{ ……..
};

derived_class_name – a name of new derived class


Base_class_name – a name of existing base class
access_control_label – it may be public, private, protected

Prepared by Brian Lam Tak Cheung 7


Class Inheritance
MessagePrinter(int r)
#include <iostream> {
#include <string> repeat = r;
}
class MessagePrinter // base class MessagePrinter
{ MessagePrinter( )
protected: {
string message; message = “You are the weakest link!”;
int repeat; repeat = 10;
};
public:
MessagePrinter (string m, int r) void print()
{ {
message = m; int i;
repeat = r ; for(i=0;i<repeat;i++)
}; cout << message << endl;
};
};
Prepared by Brian Lam Tak Cheung 8
Class Inheritance
Example 1:
class LaserPrinter : public MessagePrinter int main()
{ {
LaserPrinter LPT1;
}; LPT1.print();
}
Remarks: It inherit all the member function from MessagePrinter. However, it
inherit the Default Constructor MessagePrinter() only.

class LaserPrinter : public MessagePrinter class LaserPrinter : public MessagePrinter


{ {
public: public:
LaserPrinter(string m, int r) LaserPrinter(string m, int r)
{ {
message = m; // message = m;
repeat = r ; repeat = r ;
}; };
}; };
Prepared by Brian Lam Tak Cheung 9
Class Inheritance
class LaserPrinter : public MessagePrinter int main()
{ {
public: LaserPrinter LPT1(“Out!”,1);
LaserPrinter(string m, int r):MessagePrinter(“???”, 3) LPT1.print();
{ }
message = m;
};
> Out!
};
> Out!
class LaserPrinter : public MessagePrinter > Out!
{
public:
LaserPrinter(string m, int r):MessagePrinter(“???”, 3) From Base Class
{
message = m;
repeat = r ;
}; > Out!
};
Prepared by Brian Lam Tak Cheung 10
Over-ridding

 Can we write new data member and member function in the sub-
class?
Yes, just simple.
 Can we write our own print() function in the LaserPrinter?
Yes, by over-ridding.
 What is the different between Over-ridding and Overloading?
Overloading is different functions in a class with same function name but
different parameter list
Over-ridding is using a sub-class function to replace the base-class function.
It makes a sub-class inherit the base-class characteristics while new
characteristics can be added.

Prepared by Brian Lam Tak Cheung 11


Over-ridding
class LaserPrinter : public MessagePrinter
{ > Laser Printer :
public:
LaserPrinter(string m, int r) > Out!
{
message = m;
repeat = r ;
}; How about reuse the
code in base-class?
void print()
{
int i; void print()
cout << “Laser Printer : ” << endl; ; {
for(i=0;i<repeat;i++) cout << “Laser Printer : ” ;
cout << message << endl; MessagePrinter::print();
}; };

};

Prepared by Brian Lam Tak Cheung 12


Access Control
The derived class can set different the control access to base class.

Derived Class Properties


Base Class
Public Protected Private
Properties
Inheritance Inheritance Inheritance

Public Public Protected Private


Member Member Member Member

Protected Protected Protected Private


Member Member Member Member

Access by base Access by base


Private Access by base class member only class member only
Member class member only

Prepared by Brian Lam Tak Cheung 13


Access Control
class MessagePrinter
{ Public Inheritance:
private:
int serial_number; class LaserPrinter : public MessagePrinter
{
protected: public:
string message; LaserPrinter(string m, int r):MessagePrinter()
int repeat; {
serial_number = 9999;
public: repeat = 3;
MessagePrinter (string m, int r) // ...
{ // …. };
serial_number = 12345; void my_print() NOT
}; {
void print() OK
print();
{ };
// ...
}; }; OK
…..
}; 14
Prepared by Brian Lam Tak Cheung
Access Control

int main()
Public Inheritance: Protected Inheritance:
{
class LaserPrinter : protected MessagePrinter
LaserPrinter LPT1(“Hello World”,1);
{
cout << LPT1.serial_number << endl;
public:
cout << LPT1.repeat << endl;
LaserPrinter(string m, int r):MessagePrinter()
LPT1.print();
{
}
serial_number = 9999;
repeat = 3;
// ...
};
void my_print() NOT
Not OK { OK
OK
print();
};
}; OK

Prepared by Brian Lam Tak Cheung 15


Access Control
Protected Inheritance: Private Inheritance:
int main()
{ class LaserPrinter : private MessagePrinter
LaserPrinter LPT1(“Hello World”,1); {
cout << LPT1.serial_number << endl; public:
cout << LPT1.repeat << endl; LaserPrinter(string m, int r):MessagePrinter()
LPT1.print(); {
} serial_number = 9999;
repeat = 3;
// ...
};
void my_print() NOT
OK Not OK { OK
print();
};
}; OK

Prepared by Brian Lam Tak Cheung 16


Access Control

int main()
Private Inheritance:
{ So, what is the different between the
LaserPrinter LPT1(“Hello World”,1); protected and private inheritance?
cout << LPT1.serial_number << endl;
cout << LPT1.repeat << endl;
LPT1.print(); In protected inheritance, “repeat” and
} “print()”can be further accessed by the
sub-class of LaserPrinter, such as
HP_4L.

Not OK In private inheritance, “repeat” and


“print()” cannot be accessed by further
sub-class.

Prepared by Brian Lam Tak Cheung 17


Multiple Inheritance

 As mentioned before, one class can be a sub-class of more than


once base class. Following is an example of multiple inheritance:

class HP_4L : public LaserPrinter, public HP_Product { … }

 How about this?


class HP_4L : public LaserPrinter, HP_Product { … }

 OK, the access control of HP_Product will be set as default to


private

Prepared by Brian Lam Tak Cheung 18


Multiple Inheritance

 If HP_4L, LaserPrinter and HP_Product are implemented with


print(), how to distinguish them when calling within HP_4L?
class HP_4L : public LaserPrinter, public HP_Product
{ // ...
void function()
{ print();
HP_Product::print();
LaserPrinter::print();
}
// ...
};

Prepared by Brian Lam Tak Cheung 19


Exception Handling
 What is exception?
 The cases that we do not expected. It is run-time abnormalities.
 More simply to say - Error Handling
 Example: division by zero, access to an array outside of its bounds,
exhaustion of the free memory
 In C, we handle error like this:

int caller()
{
double ratio(int a, int b){ double r = ratio(-1,0);
if(a<0||b<0) return -1; if (r == -1)
else if(b==0) return -2; cout<<”Negative Error" << endl;
else return (a/b); else if(r == -2)
} cout<<”Zero Error" << endl;
else cout << r << endl;
}
Prepared by Brian Lam Tak Cheung 20
Exception Handling
 The previous code reduces the readability and may not the be the best
place to handle error here.
 In C++ we use exception:
 when a program detects an anomaly, an exception object is throw
 throw behaves like a return statement
 the object returned is caught by a try and catch block

double ratio(int a, int b){


#include <iostream> if(a<0||b<0) throw negativeInput();
else if(b==0) throw divideByZero();
class divideByZero {/*..*/}; return (a/b);
class negativeInput {/*..*/}; }

Prepared by Brian Lam Tak Cheung 21


Exception Handling
int caller() Negative Error is thrown.
{ Jump to catch statement
try{
double r = ratio(-1,0);
cout << “ratio = “ << r << endl; int main()
cout << ”inside try" << endl; {
} cout << "before call" << endl;
catch (divideByZero obj) try {
{ cout<<”Zero Error" << endl; caller();
// ...} }
catch (negativeInput obj) catch (negativeInput obj)
{ cout<<"Negative Error" << endl; { cout << "Rethrow" << endl;
// ... }
cout << "after call" << endl;
} }
cout << ”after catch" << endl;
}

Prepared by Brian Lam Tak Cheung 22


Exception Handling
int caller() Negative Error is thrown.
{ Jump to catch statement
try{
double r = ratio(-1,0);
cout << “ratio = “ << r << endl; int main()
cout << ”inside try" << endl; {
} cout << "before call" << endl;
catch (divideByZero obj) try {
{ cout<<”Zero Error" << endl; caller();
// ...} }
catch (negativeInput obj) catch (negativeInput obj)
{ cout<<"Negative Error" << endl; { cout << "Rethrow" << endl;
// if still cannot handle ... }
throw ; cout << "after call" << endl;
} }
cout << ”after catch" << endl;
}

Prepared by Brian Lam Tak Cheung 23


Exception Handling
int caller() Negative Error is thrown.
{ Jump to catch statement
try{
double r = ratio(-1,0);
cout << “ratio = “ << r << endl; int main()
cout << ”inside try" << endl; {
} cout << "before call" << endl;
try {
caller();
No Catch Match!? }
catch (negativeInput obj)
{ cout << "Rethrow" << endl;
}
cout << "after call" << endl;
cout << ”after catch" << endl; }
}

Prepared by Brian Lam Tak Cheung 24


Exception Handling
 how to tell the kind of exception objects that might be thrown back from a
function?
 from exception specifications

double ratio(...) throw(divideByZero,negativeInput)

In summary:
create an exception object at point of exception
pass (throw) the exception back to caller
if the caller cannot handle it, then pass (rethrow) the object to a higher
level caller
eventually back to main
if main cannot handle it, throw the object to system
program is terminated

Prepared by Brian Lam Tak Cheung 25

You might also like