Object-Oriented Programming
(OOP)
Lecture – Templates
Motivation
• Following function prints an array of
integer elements:
void printArray(int* array, int size)
{
for ( int i = 0; i < size; i++ )
cout << array[ i ] << “, ”;
}
...Motivation
• What if we want to print an array of
characters?
void printArray(char* array,
int size)
{
for ( int i = 0; i < size; i++ )
cout << array[ i ] << “, ”;
}
...Motivation
• What if we want to print an array of
doubles?
void printArray(double* array,
int size)
{
for ( int i = 0; i < size; i++ )
cout << array[ i ] << “, ”;
}
...Motivation
• Now if we want to change the way function
prints the array. e.g. from
1, 2, 3, 4, 5
to
1 - 2 - 3 - 4 - 5
...Motivation
• Now consider the Array class that wraps
an array of integers
class Array {
int* pArray;
int size;
public:
…
};
...Motivation
• What if we want to use an Array class that
wraps arrays of double?
class Array {
double* pArray;
int size;
public:
…
};
...Motivation
• What if we want to use an Array class that
wraps arrays of boolean variables?
class Array {
bool* pArray;
int size;
public:
…
};
...Motivation
• Now if we want to add a function sum to
Array class, we have to change all the
three classes
Generic Programming
• Generic programming refers to programs
containing generic abstractions
• A generic program abstraction (function,
class) can be parameterized with a type
• Such abstractions can work with many
different types of data
Advantages
• Reusability
• Writability
• Maintainability
Templates
• In C++ generic programming is done using
templates
• Two kinds
– Function Templates
– Class Templates
• Compiler generates different type-specific
copies from a single template
Function Templates
• A function template can be parameterized
to operate on different types of data
Declaration
template< class T >
void funName( T x );
// OR
template< typename T >
void funName( T x );
// OR
template< class T, class U, … >
void funName( T x, U y, … );
Example – Function Templates
• Following function template prints an array
having almost any type of elements:
template< typename T >
void printArray( T* array, int size )
{
for ( int i = 0; i < size; i++ )
cout << array[ i ] << “, ”;
}
…Example – Function Templates
int main() {
int iArray[5] = { 1, 2, 3, 4, 5 };
void printArray( iArray, 5 );
// Instantiated for int[]
char cArray[3] = { ‘a’, ‘b’, ‘c’ };
void printArray( cArray, 3 );
// Instantiated for char[]
return 0;
}
Explicit Type Parameterization
• A function template may not have any
parameter
template <typename T>
T getInput() {
T x;
cin >> x;
return x;
}
…Explicit Type
Parameterization
int main() {
int x;
x = getInput(); // Error!
double y;
y = getInput(); // Error!
}
…Explicit Type
Parameterization
int main() {
int x;
x = getInput< int >();
double y;
y = getInput< double >();
}
User-defined Specializations
• A template may not handle all the types
successfully
• Explicit specializations need to be
provided for specific type(s)
Example – User Specializations
template< typename T >
bool isEqual( T x, T y ) {
return ( x == y );
}
… Example – User Specializations
int main {
isEqual( 5, 6 ); // OK
isEqual( 7.5, 7.5 ); // OK
isEqual( “abc”, “xyz” );
// Logical Error!
return 0;
}
… Example – User Specializations
template< >
bool isEqual< const char* >(
const char* x, const char* y ) {
return ( strcmp( x, y ) == 0 );
}
… Example – User Specializations
int main {
isEqual( 5, 6 );
// Target: general template
isEqual( 7.5, 7.5 );
// Target: general template
isEqual( “abc”, “xyz” );
// Target: user specialization
return 0;
}
… Example – Function Template
#include <iostream>
using namespace std;
// Function template definition
template <typename T> T myMax(T x, T y) {
return (x > y) ? x : y;
}
int main() {
// Call myMax for int
cout << myMax<int>(3, 7) << endl;
// call myMax for double
cout << myMax<double>(3.0, 7.0) << endl;
// call myMax for char
cout << myMax<char>('g', 'e');
return 0;
}
Class Templates
• Class templates like function
templates, are useful when a class
defines something that is
independent of the data type.
• It is useful for classes like
LinkedList, BinaryTree, Stack,
Queue, Array, etc.
Example
#include <iostream>
using namespace std;
// Defining class template
template <typename T>
class A {
public:
T x;
T y;
// Constructor
A(T val1, T val2) : x(val1), y(val2) {}
// Method to get values
void getValues() {
cout << x << " " << y;
}
};
Example
int main() {
// Creating objects of A with
// different data types
A<int> intA(10, 20);
Geek<double> doubleA(3.14, 6.28);
// Access the templates values
intA.getValues();
cout << endl;
doubleA.getValues();
return 0;
}
Example
#include <iostream>
using namespace std;
// Defining class template with
// multiple type parameters
template <typename T1, typename T2, typename T3>
class A {
public:
T1 x;
T2 y;
T3 z;
// Constructor to initialization
A(T1 val1, T2 val2, T3 val3) :
x(val1), y(val2), z(val3) {}
// Method to get values
void getValues() {
cout << x << " " << y << " " << z;
}
};
Example
int main() {
// Creating objects of A
// with different data types
A<int, double, string> intDoubleStringA(10,
3.14, "Hello");
A<char, float, bool> charFloatBoolA('A', 5.67f,
true);
intDoubleStringA.getValues();
cout << endl;
charFloatBoolA.getValues();
return 0;
}
Friend Functions
►Consider the following class:
class X{
private:
int a, b;
public:
void MemberFunction();
…
}
Friend Functions
►Global function:
void DoSomething(X obj){
obj.a = 3; //Error
obj.b = 4; //Error
}
Friend Functions
►In order to access the member variables of the class,
function definition must be made a friend function:
class X{
private:
int a, b;
public:
…
friend void DoSomething(X obj);
}
►Now the function DoSomething can access data
members of class X
Friend Functions
►Prototypes of friend
functions appear in the class
definition
►But friend functions are
NOT member functions
Friend Functions
►Friend functions can be placed anywhere in the
class without any effect
►Access specifiers don’t affect friend functions or
classes
class X{
...
private:
friend void DoSomething(X);
public:
friend void DoAnything(X);
...
};
Friend Functions
►While the definition of the friend function
is:
void DoSomething(X obj){
obj.a = 3; // No
Error
obj.b = 4; // No
Error
…
}
►friend keyword is not given in definition
Friend Functions
►If keyword friend is used in the function
definition, it’s a syntax error
//Error…
friend void DoSomething(X obj){
…
}
Friend Classes
•Similarly, one class can also be made
friend of another class:
class X{
friend class Y;
…
};
•Member functions of class Y can access
private data members of class X
Friend Classes
•Example:
class X{
friend class Y;
private:
int x_var1, x_var2;
...
};
Friend Classes
class Y{
private:
int y_var1, y_var2;
X objX;
public:
void setX(){
objX.x_var1 = 1;
}
};
Friend Classes
int main(){
Y objY;
objY.setX();
return 0;
}

Focus OOP C++ programming Template Lecture32.ppt

  • 1.
  • 2.
    Motivation • Following functionprints an array of integer elements: void printArray(int* array, int size) { for ( int i = 0; i < size; i++ ) cout << array[ i ] << “, ”; }
  • 3.
    ...Motivation • What ifwe want to print an array of characters? void printArray(char* array, int size) { for ( int i = 0; i < size; i++ ) cout << array[ i ] << “, ”; }
  • 4.
    ...Motivation • What ifwe want to print an array of doubles? void printArray(double* array, int size) { for ( int i = 0; i < size; i++ ) cout << array[ i ] << “, ”; }
  • 5.
    ...Motivation • Now ifwe want to change the way function prints the array. e.g. from 1, 2, 3, 4, 5 to 1 - 2 - 3 - 4 - 5
  • 6.
    ...Motivation • Now considerthe Array class that wraps an array of integers class Array { int* pArray; int size; public: … };
  • 7.
    ...Motivation • What ifwe want to use an Array class that wraps arrays of double? class Array { double* pArray; int size; public: … };
  • 8.
    ...Motivation • What ifwe want to use an Array class that wraps arrays of boolean variables? class Array { bool* pArray; int size; public: … };
  • 9.
    ...Motivation • Now ifwe want to add a function sum to Array class, we have to change all the three classes
  • 10.
    Generic Programming • Genericprogramming refers to programs containing generic abstractions • A generic program abstraction (function, class) can be parameterized with a type • Such abstractions can work with many different types of data
  • 11.
  • 12.
    Templates • In C++generic programming is done using templates • Two kinds – Function Templates – Class Templates • Compiler generates different type-specific copies from a single template
  • 13.
    Function Templates • Afunction template can be parameterized to operate on different types of data
  • 14.
    Declaration template< class T> void funName( T x ); // OR template< typename T > void funName( T x ); // OR template< class T, class U, … > void funName( T x, U y, … );
  • 15.
    Example – FunctionTemplates • Following function template prints an array having almost any type of elements: template< typename T > void printArray( T* array, int size ) { for ( int i = 0; i < size; i++ ) cout << array[ i ] << “, ”; }
  • 16.
    …Example – FunctionTemplates int main() { int iArray[5] = { 1, 2, 3, 4, 5 }; void printArray( iArray, 5 ); // Instantiated for int[] char cArray[3] = { ‘a’, ‘b’, ‘c’ }; void printArray( cArray, 3 ); // Instantiated for char[] return 0; }
  • 17.
    Explicit Type Parameterization •A function template may not have any parameter template <typename T> T getInput() { T x; cin >> x; return x; }
  • 18.
    …Explicit Type Parameterization int main(){ int x; x = getInput(); // Error! double y; y = getInput(); // Error! }
  • 19.
    …Explicit Type Parameterization int main(){ int x; x = getInput< int >(); double y; y = getInput< double >(); }
  • 20.
    User-defined Specializations • Atemplate may not handle all the types successfully • Explicit specializations need to be provided for specific type(s)
  • 21.
    Example – UserSpecializations template< typename T > bool isEqual( T x, T y ) { return ( x == y ); }
  • 22.
    … Example –User Specializations int main { isEqual( 5, 6 ); // OK isEqual( 7.5, 7.5 ); // OK isEqual( “abc”, “xyz” ); // Logical Error! return 0; }
  • 23.
    … Example –User Specializations template< > bool isEqual< const char* >( const char* x, const char* y ) { return ( strcmp( x, y ) == 0 ); }
  • 24.
    … Example –User Specializations int main { isEqual( 5, 6 ); // Target: general template isEqual( 7.5, 7.5 ); // Target: general template isEqual( “abc”, “xyz” ); // Target: user specialization return 0; }
  • 25.
    … Example –Function Template #include <iostream> using namespace std; // Function template definition template <typename T> T myMax(T x, T y) { return (x > y) ? x : y; } int main() { // Call myMax for int cout << myMax<int>(3, 7) << endl; // call myMax for double cout << myMax<double>(3.0, 7.0) << endl; // call myMax for char cout << myMax<char>('g', 'e'); return 0; }
  • 26.
    Class Templates • Classtemplates like function templates, are useful when a class defines something that is independent of the data type. • It is useful for classes like LinkedList, BinaryTree, Stack, Queue, Array, etc.
  • 27.
    Example #include <iostream> using namespacestd; // Defining class template template <typename T> class A { public: T x; T y; // Constructor A(T val1, T val2) : x(val1), y(val2) {} // Method to get values void getValues() { cout << x << " " << y; } };
  • 28.
    Example int main() { //Creating objects of A with // different data types A<int> intA(10, 20); Geek<double> doubleA(3.14, 6.28); // Access the templates values intA.getValues(); cout << endl; doubleA.getValues(); return 0; }
  • 29.
    Example #include <iostream> using namespacestd; // Defining class template with // multiple type parameters template <typename T1, typename T2, typename T3> class A { public: T1 x; T2 y; T3 z; // Constructor to initialization A(T1 val1, T2 val2, T3 val3) : x(val1), y(val2), z(val3) {} // Method to get values void getValues() { cout << x << " " << y << " " << z; } };
  • 30.
    Example int main() { //Creating objects of A // with different data types A<int, double, string> intDoubleStringA(10, 3.14, "Hello"); A<char, float, bool> charFloatBoolA('A', 5.67f, true); intDoubleStringA.getValues(); cout << endl; charFloatBoolA.getValues(); return 0; }
  • 31.
    Friend Functions ►Consider thefollowing class: class X{ private: int a, b; public: void MemberFunction(); … }
  • 32.
    Friend Functions ►Global function: voidDoSomething(X obj){ obj.a = 3; //Error obj.b = 4; //Error }
  • 33.
    Friend Functions ►In orderto access the member variables of the class, function definition must be made a friend function: class X{ private: int a, b; public: … friend void DoSomething(X obj); } ►Now the function DoSomething can access data members of class X
  • 34.
    Friend Functions ►Prototypes offriend functions appear in the class definition ►But friend functions are NOT member functions
  • 35.
    Friend Functions ►Friend functionscan be placed anywhere in the class without any effect ►Access specifiers don’t affect friend functions or classes class X{ ... private: friend void DoSomething(X); public: friend void DoAnything(X); ... };
  • 36.
    Friend Functions ►While thedefinition of the friend function is: void DoSomething(X obj){ obj.a = 3; // No Error obj.b = 4; // No Error … } ►friend keyword is not given in definition
  • 37.
    Friend Functions ►If keywordfriend is used in the function definition, it’s a syntax error //Error… friend void DoSomething(X obj){ … }
  • 38.
    Friend Classes •Similarly, oneclass can also be made friend of another class: class X{ friend class Y; … }; •Member functions of class Y can access private data members of class X
  • 39.
    Friend Classes •Example: class X{ friendclass Y; private: int x_var1, x_var2; ... };
  • 40.
    Friend Classes class Y{ private: inty_var1, y_var2; X objX; public: void setX(){ objX.x_var1 = 1; } };
  • 41.
    Friend Classes int main(){ YobjY; objY.setX(); return 0; }