0% found this document useful (0 votes)
39 views47 pages

Lec12 (Topic 7 Advanced Topic)

The document discusses function and class templates in C++. It provides examples of function templates that allow functions to work with different data types. It also discusses class templates that allow classes to work with different data types for attributes and parameters. The document explains how to declare function and class templates and how the compiler produces separate definitions for each data type used. It also covers vectors and how to initialize, access, and perform common operations on vector elements. Finally, the document discusses friend functions and classes, which allow non-member functions or classes to access private members of other classes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views47 pages

Lec12 (Topic 7 Advanced Topic)

The document discusses function and class templates in C++. It provides examples of function templates that allow functions to work with different data types. It also discusses class templates that allow classes to work with different data types for attributes and parameters. The document explains how to declare function and class templates and how the compiler produces separate definitions for each data type used. It also covers vectors and how to initialize, access, and perform common operations on vector elements. Finally, the document discusses friend functions and classes, which allow non-member functions or classes to access private members of other classes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 47

LECTURE 12

Advanced Topic
Overview
12.1 Function Template
12.2 Class Template
12.3 Vectors
12.4 Friend Functions
12.5 Exception Handling
12.1
Function Template
Introduction
• Template allows us to write generic functions or classes
(called function template, class template) that accept any
data type as parameters or attributes.

• During compilation, the compiler will produce a separate


definition for every data type that uses the template.
Function Template
Recall the function to swap integers:

void Swap (int& m, int& n) { These 2 functions do


int temp = m; the same thing, only
m = n; different in the data
n = temp; type of objects they
} swap.
We can avoid writing
To sort string, we would need a different the redundant code by
function: replacing both
functions with a
function template.
void Swap (string& s1, string& s2) {
string temp = s1;
s1 = s2;
s2 = temp;
}
Function template
Template version of Swap() function: The symbol T is called
type parameter. It is
replaced by an actual type
template <typename T> when the function is
void Swap(T& x, T& y) { invoked.
T temp = x;
x = y;
y = temp;
}
int main() { Compiler produces 2
int m = 22, n = 66; definitions of Swap()
Swap(m, n); // integers functions: one for int,
cout << "m = " << m << endl one for string
<< "n = " << n << endl;
string s1 = "Michael", s2 = "Kelly"; Output:
Swap(s1, s2); // strings m = 66
cout << "s1 = " << s1 << endl n = 22
<< "s2 = " << s2 << endl; s1 = Kelly
return 0; s2 = Michael
}
Declaring Function Template
Function templates are declared in the same way as ordinary functions, except
that it is preceded by the specification below:

template <typename T>

and the type parameter T may be used in place of ordinary data types within the
function definition.
The word typename here means any type.
A template may have several type parameters:

template <typename T, typename U, typename V>


12.2
Class Template
Class Template
Class templates are declared the same way as ordinary class, except that it
is preceded by the specification below:

template <typename T>


class X {
...
};

A class template may have several type parameters.

template <typename T, typename U>


class X {
...
};
Class Template Class template allows us to write one
class that works for many data types

int main() {
Define a class template Pair that have 2 Pair<int> p1;
attributes of the same type. p1.set (3,5);
p1.print();
template <typename T> Pair<string> p2;
class Pair { p2.set ("Peter",
T a; "Jackson");
T b; p2.print();
public: Pair<char> p3;
void set (T a, T b) { p3.set ('P','J');
this->a = a; p3.print();
this->b = b; return 0;
} }
void print() const {
cout << "(" << a << "," Output:
<< b << ")\n"; (3,5)
} (Peter,Jackson)
}; (P,J)
Multiple Type Parameters
int main() {
Class template that can have different Pair<int,char> p1;
types of attributes p1.set (1, 'A');
p1.print();
template <typename T, typename U> Pair<char,string> p2;
class Pair { p2.set ('B',"Boy");
T a; p2.print();
U b; Pair<int,int> p3;
public: p3.set (99,99);
void set (T a, U b) { p3.print();
this->a = a; return 0;
this->b = b; }
}
void print() const {
cout << "(" << a << "," Output:
<< b << ")\n"; (1,A)
} (B,Boy)
}; (99,99)
12.3
Vectors
Vectors
• Vectors are like arrays that can change size as
your program runs
• Vectors, like arrays, have a base type
• To declare an empty vector with base type int:
vector<int> v;
• <int> identifies vector as a template class
• You can use any base type in a template class:
vector<string> v;
Initializing vector Elements
• Elements are added to a vector using the member
function push_back
• push_back adds an element in the next available position
• Example: vector<double> sample;
sample.push_back(0.0);
sample.push_back(1.1);
sample.push_back(2.2);
Accessing vector Elements
• Vectors elements are indexed starting with 0
• [ ]'s are used to read or change the value of an item:

v[i] = 42;

cout << v[i];


• [ ]'s cannot be used to initialize a vector element
The size Of A vector
• The member function size returns the number
of elements in a vector
• Example: To print each element of a vector given the previous
vector initialization:
for (int i= 0; i < sample.size( ); i++)
cout << sample[i] << endl;
Alternate vector Initialization
• A vector constructor exists that takes an integer argument
and initializes that number of elements
• Example: vector<int> v(10);

initializes the first 10 elements to 0


v.size( ) would return 10
• [ ]'s can now be used to assign elements 0 through 9
• push_back is used to assign elements greater than 9
• vector with specific initialized values
• vector<int> v(10, 999);
• vector size 10, all elements initialized to 999

• vector initialized with another vector


• aka calling the copy constructor
• vector<int> v(10, 999);
• vector<int> x(v);
The vector Library
• To use the vector class
• Include the vector library

#include <vector>

• Vector names are placed in the standard namespace so the usual


using directive is needed:

using namespace std;


Slide 8-
20
Vector’s Operations
We can use the vector class as if it is an array that can be resized
dynamically.
Another advantage of vector is it provides random access to its elements.
Common operations of vector class:

• push_back add an item to the end of the container


• pop_back remove an item from the end of the container
• operator[] return the item given a position
• front return the first item in the container
• back return the last item in the container
• size return the size of the container
• clear clear all the items in the container
vector Efficiency
• A vector's capacity is the number of elements allocated in
memory
• Accessible using the capacity() member function
• Size is the number of elements initialized
• When a vector runs out of space, the capacity is
automatically increased
• A common scheme is to double the size of a vector
• More efficient than allocating smaller chunks of memory
12.4
Friend Functions
Friendship
• Friendship allows a class to selectively grant other function or class
the access to its private and protected members.

• A friend function is a function that can access private and protected


members of a class, even though the function itself is not a member of
the class.

• A friend class is a class that can access private and protected


members of another class
Friendship
• Friendship is granted. So for a function A or class B to access the
private and protected members of class C, C must grant A and B the
friendship

• Friendship is not automatically bi-directional. When A makes B a


friend, B does not automatically make A a friend.
Example: Friend Function
// Problem
class Human {
string secret;
public:
Human (string secret)
: secret(secret) {} Error. Non-member cannot
}; access private member.
void tellSecret (Human h) {
cout << h.secret; // ERROR
}
int main() {
Human h("I have 2 gf:P\n");
tellSecret(h);
return 0;
}
Example: Friend Function
// Friend function solution
class Human {
string secret;
friend void tellSecret (Human); Grant tellSecret()
public: friendship. tellSecret()
Human (string secret) is not a member but friend
: secret(secret) {}
};
void tellSecret (Human h) {
cout << h.secret; // Fine
}
int main() { Fine. Friend function can
Human h("I have 2 gf:P\n"); access private member.
tellSecret(h);
return 0;
}
Output:
I have 2 gf:P
Example: Friend Class
// Problem int main() {
class Human { Human h("I am pretty\n");
string secret; Parrot b;
public: b.tellSecret(h);
Human (string secret) return 0;
: secret(secret) {} }
};

class Parrot {
public:
void tellSecret (Human h) {
cout << h.secret; // ERROR
} Error. Non-member
}; cannot access private
member.
Example: Friend Class
// Friend class solution int main() {
class Human { Human h("I have 2 gf:P\n");
friend class Parrot; Parrot b;
string secret; b.tellSecret(h);
public: return 0;
Human (string secret) }
: secret(secret) {}
}; Output:
class Parrot { I have 2 gf:P
public:
void tellSecret (Human h) {
cout << h.secret; // Fine
} Fine. Friend class can
}; access private member.
12.5
Exception Handling
Exception
When a program is executed, unexpected situation may occur. Such
a situation is called an exception
In other word: Exception is a runtime error caused by some
abnormal conditions

Example:
• division by zero
• failure of new operator to obtain a requested amount of memory

Exception handler is code that handles the exception (runtime error)


when it occurs
Exception Example: Division By Zero
How to deal with the error below?
double divide (double x, double y) {
return x / y; // divide by 0 if y = 0
}
int main() {
double x, y;
cin >> x >> y;
cout << "Result = " << divide (x, y);
}
Exception Example: Division By Zero
A solution is shown below. It works but the codes that handles the error
mixes with the codes for division, making the codes harder to read (if
for division, else for error handling, or the other way? No direct
indication from if/else keywords alone.

double divide (double x, double y) {


return x / y; // divide by 0 if y = 0
}
int main() {
double x, y;
cin >> x >> y;
if (y == 0) cout << "Cannot divide by zero\n";
else cout << "Result = " << divide (x, y);
}
Exception Handling
C++ implements exception handling using try, throw and catch
block.
try block:
-Write the code that might generate runtime error within the try
block.

Format: try {
// Code that may generate
// exceptions
}
try, throw, and catch blocks
throw statement:
-Use keyword throw in try block to signal that abnormal
condition or error has occurred.
-If the throw statement is executed, the codes in the try
block that appear after the throw statement won't be
executed.

Format: try {
...
throw <object>;
...
}
“<object>” is to be replaced with type of object to be thrown.
try, throw, and catch blocks
catch block:
-Write the code that catches the thrown exception in
catch block. This is the exception handler.
-Unhandled/Uncaught thrown exception will terminate the
program.

Format: try {
...
throw <object>;
...
}
// No code between try and catch
catch (<Type of Exception>) {
error handling code;
}
Example 1: try, throw, and catch blocks
int main() {
double x, y;
cin >> x >> y;
try {
if (y == 0)
throw y;
double result = x / y; Output1:No exception
cout << "Result = " << result; 1 2
} Result = 0.5
catch (double a) {
cout << "Cannot divide by zero\n";
} Output2:With exception
} 1 0
Cannot divide by zero
Example 2: try, throw, and catch blocks
double divide (double x, double y)
{ If there is an exception,
if (y == 0) throw it
throw y;
return x / y; Put code that may
} generate error in try
int main() { block
double x, y;
cin >> x >> y; If there is no exception,
try { resume execution
double result = divide (x, y);
cout << "Result = " << result;
} If there is an exception of
catch (double a) { type double,
cout << "Cannot divide by zero\ catch it
n";
}
}
double divide (double x, double y) { Output1:No exception
if (y == 0) 1 2
throw y; Result = 0.5
return x / y;
}
int main() { Output2:With exception
double x, y; 1 0
cin >> x >> y; Cannot divide by zero
try {
double result = divide (x, y);
cout << "Result = " << result;
}
catch (double a) { The type of the object
cout << "Cannot divide by zero\ being thrown must
n"; match the type of the
} parameter in the catch
} block
double divide (double x, double y) { Output1:No exception
if (y == 0) 1 2
throw y; Result = 0.5
return x / y;
}
int main() { Output2:With exception
double x, y; 1 0
cin >> x >> y; Cannot divide by zero
try {
double result = divide (x, y);
cout << "Result = " << result;
}
catch (double a) { When an exception is
cout << "Cannot divide by zero\n"; thrown, the codes that
} appear after the throw
} statement won't be
executed
Multiple catch Blocks
Some times, we might have many different exceptions for a small
block of code

1. We should write as many catch blocks.

2. This also means that we should have as


many throw statements.

3. BUT(usually), only one try block.

But, which catch block will be instigated/invoked? Depend on the


type of parameter.
The type must match exactly, no implicit conversion will be done by
C++.
Multiple catch Blocks
try {
// Code that could generate an exception
}
catch (<Exception type1>) {
// Code that resolves a type1 exception
}
catch (<Exception type2>) {
// Code that resolves a type2 exception
}
catch (<Exception typeN>) {
// Code that resolves a typeN exception
} // end-of try-catch block

Only one catch block will be executed for an exception. The catch
block that first matches the exception type would be chosen
Multiple catch Blocks
void func (int n) { int main () {
try { func (1);
if (n == 1) throw 11; // int func (3);
if (n == 3) throw 3.5; // double func (4);
cout << "n is not 1 or 3\n"; }
}
catch (double a) { // Won't catch int Output:
cout << "Catch double " << a << endl; Catch int 11
} Catch double 3.5
catch (int a) { // First match int n is not 1 or 3
cout << "Catch int " << a << endl;
}
catch (int a) { // 2nd int, never executed
cout << "Hello\n"; No implicit
} conversion of
} exception type in
catch argument
Exception Matching
• To catch every possible exception type, use ellipsis "…"

try {
}
catch (...) { // catches all exceptions
}

Limitations of catch (...)


• You can't tell what type of exception occurred
• No argument to reference
• Should always be placed as the last catch
Exception Matching
void func (int n) { int main () {
try { func (1);
if (n == 1) throw 11; // int func (2);
if (n == 2) throw string("abc"); func (3);
if (n == 3) throw 3.5; // double func (4);
cout << "n is not 1, 2 or 3\n"; }
}
catch (double a) {
cout << "Catch double " << a << endl; Output:
} Not double nor string
catch (string a) { Catch string abc
cout << "Catch string " << a << endl; Catch double 3.5
} n is not 1, 2 or 3
catch (...) { // all types
cout << "Not double nor string\n";
}
}
Advantages of Exception Handling

Using try, throw, and catch blocks to handle


exception offer the following advantages:

1. Provide clarify on the sections of codes that handle


the error.

2. You may throw an exception in a function/method,


and handle it somewhere else
The End

You might also like