0% found this document useful (0 votes)
43 views

DS Lecture03

The document discusses classes, exceptions, and templates in C++. It covers two-dimensional arrays implemented as arrays of pointers to one-dimensional arrays. It also discusses class structure including data members, member functions, access control keywords like public and private, and usage of classes including constructors, destructor, and member functions. Initialization lists are introduced to initialize member variables that are classes without an assignment operator.

Uploaded by

Pnz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views

DS Lecture03

The document discusses classes, exceptions, and templates in C++. It covers two-dimensional arrays implemented as arrays of pointers to one-dimensional arrays. It also discusses class structure including data members, member functions, access control keywords like public and private, and usage of classes including constructors, destructor, and member functions. Initialization lists are introduced to initialize member variables that are classes without an assignment operator.

Uploaded by

Pnz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

505 22240 / ESOE 2012 Data Structures: Lecture 3

Classes, Exceptions, and Templates

§ Two-Dimensional Array and Pointer


 A two-dimensional array is implemented as an “array of arrays”.
 Two-dimensional array: an array of references (pointers) to one-dimensional arrays. § Classes
 Pascal’s Triangle: Class Structure
 A class consists of members:
Data members (member variables): variables or constants.
Member functions (methods): define behavior of the class.
 Example: Counter
 row i represents coefficients of (x+1)i class Counter {
e.g. (x + 1)4 = 𝑥 4 + 4𝑥 3 + 6𝑥 2 + 4𝑥 + 1 public: // access control
int** pascalTriangle(int n) { Counter( ); // initialization
int** pt = new int*[n]; int getCount( ); // get the current count
for (int i = 0; i < n; i++) { void increaseBy(int x); // add x to the count
pt[i] = new int[i+1]; private: // access control
pt[i][0] = 1; // left 1 int count; // the counter’s value
for (int j = 1; j < i; j++) { };
// middle values  Definitions of member functions
pt[i][j] = pt[i-1][j-1] + pt[i-1][j]; Counter::Counter( ) // constructor
} {count = 0;}
pt[i][i] = 1; // right 1 int Counter::getCount( ) // get current count
} {return count;}
return pt; void Counter::increaseBy(int x) // add x to the count
} {count += x;}
3-1
 Usage void setMonth(int m) {
Counter ctr; // an instance of Counter month = m;
cout << ctr.getCount( ) << endl; }
// prints the initial value 0 public:
ctr.increaseBy(3); // increase by 3 Date(int month, int day) {
cout << ctr.getCount( ) << endl; // prints 3 [Implementation with error-checking code here.]
ctr.increaseBy(5); // increase by 5 }
cout << ctr.getCount( ) << endl; // prints 8 };
 Note: if no access specifier is given, the default is private for classes and public for  execution:
structures. Date d(10, 12);
d.day = 26; // Failed
The “public” AND “private” Keywords d.setMonth(4); // Failed again
 public: anyone can access.
 private: method or field is invisible & inaccessible to other classes. Member Functions
→ Instance variables are normally declared private and methods are normally  Two major categories:
declared public. Accessor functions: only read class data, with ”const”.
 Why use “private”? Update functions: can alter class data.
 To prevent data from being corrupted by other classes.  Example: Passenger
 You can improve the implementation without causing other classes that depend on class Passenger {
it to fail. public:
 e.g. Passenger( ); // constructor
class Date { //In-class function
private: bool isFrequentFlyer( ) const {return isFreqFlyer;}
int day; void makeFrequentFlyer(const string& newFreqFlyerNo);
int month; private:
//… string name;
3-2
MealType mealPref; name = nm;
bool isFreqFlyer; mealPref = mp;
string freqFlyerNo; isFreqFlyer = (ffn != “NONE”); // true only if ffn is given
}; freqFlyerNo = ffn;
}
void Passenger::makeFrequentFlyer(const string& // copy constructor
newFreqFlyerNo) { Passenger::Passenger(const Passenger& pass) {
isFreqFlyer = true; name = pass.name;
freqFlyerNo = newFreqFlyerNo; mealPref = pass.mealPref;
} isFreqFlyer = pass.isFreqFlyer;
freqFlyerNo = pass.freqFlyerNo;
Constructors }
Passenger( ); // default constructor
Passenger(const string& nm, MealType mp, const string&  Usage
ffn=“NONE”); // “NONE” is default argument Passenger P1; // default constructor
Passenger(const Passenger& pass); // copy constructor Passenger P2(“John Smith”, VEGETARIAN, “293145”);
 Definitions of constructors // 2nd constructor
Passenger::Passenger( ) { // default constructor Passenger P3(“Peter Jackson”, REGULAR);
name = “--NO NAME-- ”; // not a frequent flyer
mealPref = NO_PREF; Passenger P4(P3); // copied from P3
isFreqFlyer = false; Passenger P5 = P2; // copied from P2
freqFlyerNo = “NONE”; Passenger* PP1 = new Passenger; // default constructor
} Passenger* PP2 = new Passenger(“John Blow”, NO_PREF);
// constructor given member values // 2nd constructor
Passenger::Passenger(const string& nm, MealType mp, const Passenger pa[20]; // default constructor
string& ffn) {
3-3
Initializer List: to deal with initialization of member variables that are classes size = n;
(without an assignment operator, =) : member_name(initial_value), … data = new int[n]; // allocate array
 Rewrite the 2nd Passenger constructor: }
Passenger::Passenger(const string& nm, MealType mp, const
string& ffn) : name(nm), mealPref(mp), isFreqFlyer(ffn != Vect::~Vect( ) { // destructor
“NONE”) { freqFlyerNo = ffn; } delete [ ] data; // free the allocated array
}
Destructors
 The destructor for a class T is denoted as ~T: no arguments and no return type. Memory Allocation
 Example  Using Vect class:
class Vect { Vect a(100); // a is a vector of size 100
public: Vect b = a; // initialize b from a (DANGER!)
Vect( ); // default constructor Vect c; // c is a vector (default size 10)
Vect(int n); // constructor, given size c = a; // assign a to c (DANGER!)
~Vect( ); // destructor  Shallow copy: a shallow copy of an object (collection, or class) copies all of the
private: member field values, i.e., a copy of the class structure, not the elements. With a
int* data; // an array shallow copy, two collections share the individual elements.
int size; // number of array entries Vect b = a sets b.data = a.data (pointer copy)
}; c = a lost the pointer to c’s original 10-element array. → memory leak
 a, b, and c all have members that point to the same array.
Vect::Vect() { // default constructor  Copy constructor: for a class T → T(const T& t)
size = 10;  Deep copy:
data = new int[10]; // copy constructor from a
} Vect::Vect(const Vect& a) {
size = a.size; // copy size
Vect::Vect(int n) { // constructor with given size data = new int[size]; // allocate new array
3-4
for (int i = 0; i < size; i++) { The “friend” keyword
data[i] = a.data[i]; // copy the contents  to access protected and private member data of other classes.
}  Friend function:
} class SomeClass {
// assignment operator from a private:
Vect& Vect::operator=(const Vect& a) { int secret;
if (this != &a) { // avoid self-assignment public:
delete [ ] data; // delete old array friend ostream& operator<<(ostream& out, const SomeClass&
size = a.size; // set new size x); // give << operator access to secret
data = new int[size]; // allocate new array };
for (int i = 0; i < size; i++) { ostream& operator<<(ostream& out, const SomeClass& x)
data[i] = a.data[i]; // copy the contents { cout << x.secret; }
}  Multiple classes:
} class Humidity;
return *this; class Temperature {
} private:
 For any instance of a class object, “this” is defined to be the address of this int m_nTemp;
instance. public:
Temperature(int nTemp) { m_nTemp = nTemp; }
 Every class that allocates its own objects using new should: friend void PrintWeather(Temperature& cTemperature,
 Define a destructor to free allocated objects. Humidity& cHumidity);
 Define a copy constructor, which allocates its own new member storage and };
copies the contents of member variables. class Humidity {
 Define an assignment operator, which deallocates old storage, allocates new private:
storage, and copies all member variables. int m_nHumidity;
public:
3-5
Humidity(int nHumidity) { m_nHumidity = nHumidity; } Vector Matrix::multiply(const Vector& v) {
friend void PrintWeather(Temperature& cTemperature, Vector w;
Humidity& cHumidity); for (int i = 0; i < 3; i++)
}; for (int j = 0; j < 3; j++)
w.coord[i] += a[i][j] * v.coord[j];
void PrintWeather(Temperature& cTemperature, Humidity& // access to coord of v allowed
cHumidity) { return w;
std::cout << "The temperature is " << cTemperature.m_nTemp }
<< " and the humidity is " << cHumidity.m_nHumidity <<
std::endl; Nesting Classes
} class Book {
public:
 Friend class class Bookmark {
class Vector { // a 3-element vector //… (Bookmark definition here)
public: //… };
private: //… (Remainder of Book definition)
double coord[3]; };
friend class Matrix; // give Matrix access to coord Use Book::Bookmark to refer to this nested class.
};
class Matrix { // a 3×3 matrix Interface of a Class
public:  Prototypes for public methods,
Vector multiply(const Vector& v);  plus descriptions of their behaviors.
// multiply by vector v
private: Abstract Data Type (ADT)
double a[3][3];  A class with a well-defined interface, but implementation details are hidden from
}; other classes.
3-6
Invariant § Exceptions
 A fact about a data structure that is always true.  When a run-time error occurs in C++: it ”throws an exception”  (Exception object).
 e.g, “A Date object always represents a valid date.”  Prevent the error by “catching” the Exception.
Purpose: surviving errors
 Not all classes are ADTs! Some classes just store data (no invariants).  By catching exceptions, you can recover from an unexpected error.
 e.g.: try to open a file that doesn’t exist. You can catch exception, print error
STL Vector Class message, and continue.
 A vector can be resized dynamically. try {
 Each instance of an STL vector can only hold objects of one type. fin.open(“~esoe/ds/exam.pdf”, ios::in);
 Example: getline(fin, str, ‘\n’);
#include <vector> //…
using namespace std; }
catch (FileNotFoundException& e1) {
vector<int> scores(100); // 100 integer scores cout << “Error msg … ”;
vector<char> buffer(500); // buffer of 500 characters }
vector<Passenger> passenList(20); // list of 20 Passengers catch (IOException& e2) {
fin.close( );
int i = 12; }
cout << scores[i]; // index (range unchecked) What does this code do?
buffer.at(i) = buffer.at(2*i); // index (range checked) (a) Executes the code inside “try”.
(b) If “try” code executes normally, skip “catch” clauses.
vector<int> newScores = scores; (c) If “try” code throws an exception, do not finish the “try” code. Jumps to first
// copy scores to newScores “catch” clause. “Matches” exception object thrown is the same class/subclass of
scores.resize(scores.size() + 10); exception type in “catch” clauses.
// add room for 10 more elements  When the “catch” clause finishes executing, jumps to the next line of code after all
catch clauses.
3-7
 Only the first matching “catch” is executed. Exception specification
 Each “catch” clause is called an exception handler.  When we declare a function, we should also specify the exceptions it might throw.
 Use “catch (…)” to catch all exceptions. → last handler. void calculator( ) throw (ZeroDivide, NegativeRoot) {
//…
Exception constructors try {
 Exception types often form hierarchies. //…
 e.g.: one generic exception, MathException, representing all types of if (divisor == 0)
mathematical errors. throw ZeroDivide(“Divide by zero in Module X”);
class MathException { }
public: catch (ZeroDivide& zde) {
MathException(const string& err): errMsg(err) { } // handle division by zero.
// constructor }
string getError( ) {return errMsg;} catch (MathException& me) {
// access error message // handle any math exception other than division by zero.
private: }
string errMsg; // error message //…
}; }
 Using inheritance to define new exception types:  If a function does not provide a “throw” specification, it may throw any exception.
class ZeroDivide : public MathException { void fcn1( ); // can throw any exception
public: void fcn2( ) throw( ); // can throw no exceptions
ZeroDivide(const string& err): MathException(err) { }
}; // divide by zero A generic exception class
class NegativeRoot : public MathException {  Serves as the “mother of all exceptions”.
public: class RuntimeException { // Base class
NegativeRoot(const string& err): MathException(err) { } private:
}; // negative square root string errorMsg;
3-8
public: Class Templates
RuntimeException(const string& err) {errorMsg = err;}  A simple class template:
string getMessage( ) const {return errorMsg;} template <typename T>
}; class BasicClass {
public:
BasicClass(const T& t): myObj(t) { } // constructor
§ Templates T Get( ) const {return myObj;}
 Allow functions and classes to operate with generic types, to work on multiple void Set(const T& t) {myObj = t;}
data types without being written for each one. private:
Function Templates T myObj;
 e.g. minimum of two integers: };
int integerMin(int a, int b) {return (a < b ? a : b);}  To instantiate a concrete instance of the class BasicClass, provide the class name
 A generic function for an arbitrary type T: followed by the actual type parameter enclosed in angled brackets (< … >).
template <typename T> BasicClass<float> f;
T genericMin(T a, T b) {  Use typedef to make your code more readable:
return (a < b ? a : b); typedef BasicClass<float> Float;
} Float f(5.5f);
cout << f.Get( ) << endl;
 The compiler looks at the argument types and determines which form of the function f.Set(12.3f);
to instantiate. cout << f.Get( ) << endl;
cout << genericMin(3, 4) << ‘ ‘
// = genericMin<int>(3, 4) typedef BasicClass<string> String;
<< genericMin(1.1, 3.1) << ‘ ‘ String s(“Steve”);
// = genericMin<double>(1.1, 3.1) cout << s.Get( ) << endl;
<< genericMin(‘t’, ‘g’) << endl; s.Set(“Apple”);
// = genericMin<char>(‘t’, ‘g’) cout << s.Get( ) << endl;
3-9

You might also like