Upload
sydney-richards
View
227
Download
3
Embed Size (px)
Citation preview
Object Oriented Programming in
C++
Chapter 9
Exceptions
Reasons for Exceptions not enough resources unexpected environment inconsistent data structures erroneous input
Measures: terminate the program return a value representing “error” return a legal value and leave the program in an illegal
state call an error function supplied by the caller open a dialog box asking the user for help
Traditional Error Handling Error handling normally done at location in the code that errors
are expectede.g.if ((counter = new int) == 0)
{cout << “Cannot allocate memory”.;exit(-1);
} Advantage: Error handling code where it may be used.
Drawback: More cluttered code and need to anticipate all error situations
Error Handling in the Array Example?template <class T> class Array {
public:explicit Array(int len_):
len(len_), buff(new T[len]){}~Array(void) { delete[] buff; }
int size(void) const { return len; }T& operator[](int i) {
if (0 > i || i >= size()) ???
return buff[i]; }
const T& operator[](int i) const { return (*const_cast<Array<T> * const>this)[i];
} private:
const int len;T * const buff;
Array(const Array &);Array & operator =(const Array &);
};
Error Handling in the Stack Example?template<class T> class Stack {
Array<T> a;size_t sp;
public:Stack(size_t n): sp(0), a(n) {}
int empty(void) { return sp == 0; }int full(void) { return sp == a.size(); }void push(T e) {
if (full()) ???
a[sp++] = e;}
T pop(void) { if (empty())
??? return a[--sp];
}};
Exceptions - overview Code that may result in an exception is placed
in a try block When an exception is detected the throw
operator is used to throw the exception - rather like a return statement
Control is transferred immediately from the throw to an exception handler, skipping any further code
The exception handler is a number of catch clauses that catch the exceptions thrown by the try block and try to deal with them
Basic Exception Mechanism in C++
try {try { DoTheWork;DoTheWork; };};catch(. . .) {catch(. . .) { // an exception has occurred, handle it// an exception has occurred, handle it // for example// for example // cout<<“your attempt failed, try again”,// cout<<“your attempt failed, try again”, // OR// OR // cout< “something went wrong! Bye”; // cout< “something went wrong! Bye”; exit(1);exit(1);}}
void DoTheWork(){void DoTheWork(){ Step1;Step1; Step2;Step2; Step3;Step3;}}
void StepN(){void StepN(){ dosomething;dosomething; if (<unexpected case>)if (<unexpected case>) throw;throw; domore;domore;}}
Exampleclass ZeroDivide { };float divide(int n1, int n2){
if (n2 == 0) throw ZeroDivide();return (float) n1 / n2;
}main(){
int a, b;cin >> a >> b;try {
float c = divide(a,b);cout << “a / b = “ << c << ‘\n’;
}catch (ZeroDivide) {
cout << “attempt to divide by zero\n”;}
}
Classes used in Exceptions
In many cases it is better to throw up the stack objects of a dedicated type.
class Range {};
class Overflow {};
class Underflow {};
Throwing from the Stack Code
template<class T> class Stack { ...
public: Stack(size_t n) : N(n),sp(0),buff(new T[N]) {}...void push(T e) {
if (full()) throw Overflow();
buff[sp++] = e;}T pop(void) {
if (empty()) throw Underflow();
return buff[--sp]; }
};
Throwing from the Array Code
template<class T> class Array { const size_t N; T *buff;
public: Array(size_t n): N(n), buff(new T[N]) {}
~Array(void) { delete[] buff; }T& operator[] (size_t i) {
if (i < 0 || i >= N)throw Range();
return buff[i];}
};
Catching Array Errorsvoid f(size_t n){
Array<int> v(n);v[n + 1] = 7; // causes range exception
}void g(size_t n){ ...
try { // exceptions here are handled by ... // the handler defined below
f(n); // might cause a range exception ...
}catch (Range) {
error("Range error");return;
}catch (Allocation) {
error("Memory allocation error");return;
}}
Exceptions and Nested Types
class Date {public:
class Feb29Error {};Date(int d, int m, int y) {
...if (m == 2 && d == 29 && !leap(y))
throw Feb29Error();...
}...
};
Catching Nested Type Exceptionsf(int d, int m, int y) {
Date today(d, m, y);...
}g() {
...f(i1,i2,i3);...
}
h() {try {
...g();...
} catch (Date::Feb29Error) {// Handle this error
}
}
Passing Data with Exceptionsclass Array {
int* v;int lower, upper;
public:class SubscriptError {
int index;public:
SubscriptError(int i) : index(i) { }int get() { return index; }
}Array(int, int);
int& operator[](int);...
};int& Array::operator(int i){
if (i>=lower && i<=upper) return *(v+i-lower);throw SubscriptError(i);
}
Using the information
void fun(Array& a){ ...
try {g(a); ...
}catch (Array::SubscriptError s) {
cerr << “illegal subscript:” << s.get() << ‘\n’;...
}...
}
Exceptions and Inheritancestruct StdlibError{};
struct NoMem: StdlibError{};
struct MathError: StdlibError{};struct ZeroDivide: MathError{};struct BadArcsinArg: MathError{};struct BadLnArg: MathError{};....
struct IoError: StdlibError{};struct NetworkError: StdlibError{};...struct NetworkFileError: NetworkError, FileSystemError{};
Catching Derived Exceptionstry {
...
} catch (ZeroDivide) {...
} catch (BadArcsinArg) {...
} catch (MathError) {// Exception handler for all remaining math errors
} catch (IoError) {// Exception handler for I/O errors (that are not math errors)
} catch (StdlibError) {// Exception handler for all other standard library errors
} catch (...) { // The syntax for catching all exceptions// Exception handler for all other errors
}
What’s in a Catch Block?
try {...
} catch (SomeError) {if (SomethingCanBeDone()) DoIt();
else throw;
}
Function Throw List:Interface Specification
double sqrt(double) throw(MathError);
Complex sqrt(Complex) throw(); // No exceptions!
void f() throw(ExcType1, ExcType2);// May throw exceptions of type ExcType1 or ExcType2
Object Oriented Programming in
C++
Chapter 10
Multiple Inheritance
What? How? Multiple Inheritance: the ability to define a class which
inherits from more than one class. C++ syntax:
class Student { ... } ;class Employee { ... } ;
class StudentEmployee:public Student , public Employee {
// ...} ;
Examples of Multiple Inheritance Multiple Criteria:
• GUI System:• Window Contents: text, editable, ...• Data Structure: tree, leaf, ...
• Data Structures:• Operations Supported: Stack, Queue, Dictionary, Set,
Heap, ...• Memory Organization: List, Array, Tree,...• Properties: Garbage Collected, Storable, ...
• Organization and Personnel:• Skills: Engineer, Sales person, Programmer, ...• Responsibility: Manager, Vice-President, President, ...
Coincidental:• Seaplane is a kind of an air vehicle and a water vehicle.• Platypus is a kind of a mammal and a kind of a bird.
The Problems of Multiple Inheritance
Repeated Inheritance: a base occurs more than once in the parents list.
Ambiguity: a feature occurs more than once among the parents.
Methods Combination: in refinement, one needs to collect the refined methods to call from many parents.
Linearization: definining an order among parents.
Diamond Inheritance Diamond: same base class occurs in more than one
ancestor.• Occurs in every large system.
• Must occur if the inheritance hierarchy has a common root. Classical Example:
File
File
Input FileInput File Output File
Output File
Input Output File
Input Output File
Approach to Repeated Inheritance
Either single or multiple copies of common base class.• C++’s approach: decision made by
designer of B1 and B2.BB
B1B1 B2
B2
DD
Multiple Occurrences of a Baseclass DiskPointer: public List::Node {
// The link is used to maintain a linked // list of all Disk Pointers.
};
class DisplayedObject: public List::Node {// The link is used to maintain a linked // list of all DisplayedObjects.
};
class DisplayedDiskPointer: public DiskPointer,public DisplayedObject
{// This class is used for visualization of the// caching algorithm.
};
Two Separate Objects from a Common Base Class
List::NodeList::Node
DisplayedObjectDisplayedObject DiskPointerDiskPointer
DisplayedDiskPointer
List::NodeList::Node
ClassdiagramDiskList
DisplayList
Objectdiagram
Single Occurrence of a Common Base Class
class Array { const int n; int *const data; //...};
class CheckedArray: public virtual Array { //...};
class InitArray: public virtual Array {// ...
};class InitCheckedArray: public CheckedArray,public InitArray {
// ...};
The virtual keyword causes InitCheckedArray to contain a single subobject of class Array instead of two.
The Ambiguity Problem Circumstances: Let Derived be inherited
from Base1 and Base2• All feature names inside Base1 are distinct.
• All feature names inside Base2 are distinct.
• All feature names inside Derived should be distinct.
Ambiguity Problem: the same feature name X occurs both in Base1 and in Base2• The problem does not occur in single-inheritance.
• If the same feature name occurs both in Derived and in Base, then no ambiguity occurs.
Ambiguity Resolution by Designer
class HierarchicalScreenObject: protected TreeNode,public ScreenObject {
public:void saveOn(ostream& s){
TreeNode::saveOn(s);ScreenObject::saveOn(s);//// Save own data.//
}};
Ambiguity of Up-Castingclass A {};class B: public A {};class C: public A {};class D: public B, public C {};
B *B_base(D *p) { return p;
}C *C_base(D *p) {
return p; }A *A_base(D *p) {
return p; // Compilation error
} A *A_B_base(D *p) {
return B_base(p); }A *A_C_base(D *p) {
return C_base(p); }
DB DC
D
ABA
B
CAA
CDA
???
Repeated Base Ambiguity Examplestruct Win {
virtual void draw(void)=0;// ...
};
struct Win_Menu : Win {void draw(void);//...
};
class Win_Frame_Menu: public Win_Frame, public Win_Menu {
// No draw here};
struct Win {virtual void draw(void)=0;// ...
};
struct Win_Frame : Win {void draw(void);//...
};
Win_Frame_Menu* pwfm;
pwfm->Win_Menu::draw(); // ambiguity resolution
Win* pw = static_cast<Win_Frame*>pwfm;
pw->draw(); // Win_Frame::draw used
Example of Virtual Base Ambiguitystruct Win {
virtual void draw(void) = 0;virtual void hide(void) = 0;virtual void move(Vector d) { hide(); pos += d; draw(); }
// ...};
struct Win_Menu : public virtual Win {// No draw here!void hide(void);//...
};
struct Win_Frame : public virtual Win {
void draw(void);void hide(void);//...
};
class Win_Frame_Menu : public Win_Frame, public Win_Menu {
// No draw and hide here!// ...
}; Win_Frame::draw() is dominant and is selected
Compilation error: ambiguous inheritance of hide()!
Constructors and Virtual Base Class?
class V { public: V(const char *s){ cout << s;}
};
class D: public B1, public B2 { public:
D(void): B1("DB1"), B2("DB2") {}} d;
class B1: public virtual V { public:
B1(const char *s): V("B1"){cout << s;
}};
class B2: public virtual V { public:
B2(const char *s): V("B2"){cout << s;
}};
Virtual Base Initilizationclass V { public: V(); V(int); ...};class A: public virtual V { public: A(); A(int i): V(i) { /* ... */ } ...};class B : public virtual V { public: B(); B(int i) { /* ... */ } ...};class C : public A, public B { public: C(int i): V(i) { /* ... */ } ...};
V v(1); // use V(int)A a(2); // use V(int)B b(3); // use V()C c(4); // use V(int)
Method Combinationstruct Person {
...virtual void printOn(ostream& s) { // Print person data: name, gender, etc.}
};
struct Student: public virtual Person {...void printOn(ostream& s){
Person::printOn(s); // Print student data: courses, year, etc.
} };
struct Teacher: public virtual Person {...void printOn(ostream& s) {
Person::printOn(s);// Print teacher data: salary, teaching experience, etc.
} };
Using a Virtual Base Class
struct TeachingAssistant: public Student, public Teacher {
...void printOn(ostream& s){
Student::printOn(s);Teacher::printOn(s);// Print Teaching Assistant data: Teaching supervisor, etc.
}
};
// BUG: Person's data will be printed twice!
Methodology for Method Combinationstruct Person {
void _printOn(ostream& s) {Print person’s data}void printOn(ostream& s) { _printOn(s); }
};
struct Student: public virtual Person {void _printOn(ostream& s) {Print student’s data} void printOn(ostream& s) {
Person::printOn(s);_printOn(s);
}};
struct Teacher: public virtual Person {void _printOn(ostream& s) {Print teacher’s data} void printOn(ostream& s) {
Person::printOn(s);_printOn(s);
}};
Combining the Methods
struct TeachingAssistant: public Student, public Teacher {
void _printOn(ostream& s){// Print teaching assistant’s
data
} void printOn(ostream& s) {
Person::printOn(s);Student::_printOn(s);Teacher::_printOn(s);_printOn(s);
}
};
Person
Student Teacher
TeachingAssistant