SE - Lecture 03-30 (OOP in C++)
SE - Lecture 03-30 (OOP in C++)
Programming in C++
CS20006:SoftwareEngineering
Lecture 03Prof.Partha Pratim Das
Jan-Feb 2016
PROGRAMMING IN C++
Jan-Feb 2016
Topics
PROCEDURAL
ENHANCEMENTS IN C++
Jan-Feb 2016
TOPICS
Const-ness
Reference Data Type
Inline Functions
Default Function Parameters
Function Overloading & Resolution
Dynamic Memory Allocation
Jan-Feb 2016
const Quantifier
const qualifier transforms an object into a
constant.
Example: const int capacity = 512;
Any attempt to write a const object is an error
Const object must be initialized.
References
A reference is an additional name / alias
/ synonym for an existing variable
Declaration of a Reference
<type> & <name> = <existing variable>;
Examples of Declaration
int j = 5;
int& i = j;
Jan-Feb 2016
References
Wrong declarations
int& i;
// must be initialized
int& j = 5;
// may be declared as const reference
int& i = j+k; // may be declared as a const reference
Jan-Feb 2016
References Do not ..
Cannot have an array of references
No operator other than initialization are valid on a
reference.
Cannot change the referent of the reference (Reference
can not be assigned)
Cannot take the address of the reference
Cannot compare two references
Cannot do arithmetic on references
Cannot point to a reference
Call-by-Reference
Calling by Reference
Parameters can be passed by
reference w/o copy
A reference parameter is an in-out
parameter (read-write)
Recall: A call-by-value parameter is
an input parameter
A const reference parameter is an
input only parameter (read-only)
Jan-Feb 2016
10
Call-by-Reference
Thumb Rules
Pass parameters of built-in types by
value
Recall: Array parameters are passed
by reference in C
Pass parameters of user-defined
types by reference
Make a reference parameter const if it
is not used for output
Jan-Feb 2016
11
Returning a Reference
Returning a reference
return value is not copied back
may be faster than returning a value
calling function can change returned
object
cannot be used with local variables
Jan-Feb 2016
12
Example
Jan-Feb 2016
13
Returning a Reference
#include <iostream>
using namespace std;
int& max(int& i, int& j) {
if (i > j)
return i;
else
return j;
}
int main(int, char *[]) {
int x = 42, y = 7500, z;
z = max(x, y) ; // z is now 7500
max(x, y) = 1 ; // y is now 1
cout << "x = " << x;
cout << " y = " << y;
cout << " z = " << z << "\n";
return 0;
}
Jan-Feb 2016
14
Jan-Feb 2016
15
Macros
Macros are expanded at the places of their calls.
Advantages:
Speed-wise efficient
Disadvantages:
Parameter passing mechanism is not robust and
frequently leads to errors.
Type checking during parameter passing is not done
Typical Use:
Small code re-use
Jan-Feb 2016
16
Inline Functions
Inline functions act like functions
They
Type
They
They
Jan-Feb 2016
17
Inline Notes
inline specification is only a
recommendation.
A recursive or a large function may not
be inline.
Unlike a non-inline function, an inline
function must be defined in every text
file where it is called.
Inline functions must not have two
different definitions.
May cause unexpected behavior if compiler
does not chose to make the function inline.
Jan-Feb 2016
18
19
// Error
// OK
// Error Redefinition
Wrong example:
#include ff.h
ff(int i, float f = 0.0, char ch = a); //Error
20
Function Overloading
The same function name may be used in several definitions.
Functions with the same name must have different number of
formal parameters and/or different types of formal
parameters.
Function selection based on number and types of the actual
parameters at the places of invocation.
Function selection (Overload Resolution) is performed by the
compiler
Two functions having the same signature but different return
types will result in a compilation error due to attempt to redeclare.
Overloading allows static polymorphism
Jan-Feb 2016
21
Overload Resolution
Steps to resolve overloaded functions
with one parameter
Identify the set of candidate functions and
the set of viable functions.
Select the best viable function through
(Order is important)
Jan-Feb 2016
Exact Match
Promotion
Standard type conversion
User defined type conversion
22
Overload Resolution
Steps to resolve overloaded functions
with one parameter
Example:
1. void f();
2. void f(int);
3. void f(double, double = 3.4);
4. void f(char, char *);
f(5.6)
Candidate function: 2 & 3
Best function: 3
Jan-Feb 2016
23
Exact Match
lvalue-to-rvalue conversion
Most common
Array-to-pointer conversion
Definitions: int ar[10]; void f(int *a);
Call: f(ar)
Function-to-pointer conversion
Definitions: typedef int (*fp) (int);
void f(int x, fp); int g(int);
Call: f(5, g)
Qualification conversion
Converting pointer (only) to const pointer.
Jan-Feb 2016
24
Jan-Feb 2016
25
Examples of Resolution
int f(int, int)
{ cout << "int f(int, int)" << endl; return 0; }
void f(int, void *)
{ cout << "void f(int, void *)" << endl; return; }
void f(int, char *)
{ cout << "void f(int, char *)" << endl; return; }
double f(int)
{ cout << "double f(int)" << endl; return 0.0; }
int f(double)
{ cout << "int f(double)" << endl; return 0; }
void f()
{ cout << "void f()" << endl; return; }
void f(int[])
{ cout << "void f(int[])" << endl; return; }
typedef void (*fp) (int);
void f(int x, fp)
{ cout << "void f(int x, fp)" << endl; return; }
void g(int) {} void h(int) {}
Jan-Feb 2016
26
Examples of Resolution
int f(int, int);
void f(int, void *);
void f(int, char *);
double f(int);
int f(double);
void f();
void f(int[]);
typedef void (*fp) (int);
void f(int x, fp);
void g(int) {}
void h(int) {}
Jan-Feb 2016
int main() {
int a = 2, b = 3, *q = &a;
char *p = 0; double d = 5.2;
f(a, b);
// int f(int, int)
f(a, p);
// void f(int, char *)
f(a);
// double f(int)
f(d);
// int f(double)
f();
// void f()
27
Examples of Resolution
int f(int, int);
void f(int, void *);
void f(int, char *);
double f(int);
int f(double);
void f();
void f(int[]);
typedef void (*fp) (int);
void f(int x, fp);
void g(int) {}
void h(int) {}
Jan-Feb 2016
int main() {
int a = 2, b = 3, *q = &a;
char *p = 0; double d = 5.2;
...
f(4, 5);
// int f(int, int)
f(8, q);
// void f(int, void *)
f(7);
// double f(int)
f(7.0);
// int f(double)
f(4.6, 5);
// int f(int, int)
28
Examples of Resolution
int f(int, int);
void f(int, void *);
void f(int, char *);
double f(int);
int f(double);
void f();
void f(int[]);
typedef void (*fp) (int);
void f(int x, fp);
void g(int) {}
void h(int) {}
Jan-Feb 2016
int main() {
int a = 2, b = 3, *q = &a;
char *p = 0; double d = 5.2;
...
f(q);
// void f(int[])
f(5, &g);
// void f(int x, fp)
f(5, h);
// void f(int x, fp)
return 0;
}
29
int
const
int
int&
const int&
int
redef
error
int a, b;
f(a); //
f(a+b); //
f(7); //
int a, b;
f(a); //
f(a+b); //
f(7); //
const int
int a, b;
f(a); //
f(a+b); //
f(7); //
int a, b;
f(a); //
f(a+b); //
f(7); //
int&
const int&
Jan-Feb 2016
int a, b;
f(a); //
f(a+b); //
f(7); //
X
30
int
const
int
int&
const int&
int
redef
error
int a, b;
f(a); // ambiguous
f(a+b); // ok int
f(7); // ok int
int a, b;
f(a); // ambiguous
f(a+b); // ambiguous
f(7); // ambiguous
const int
int a, b;
f(a); // ambiguous
f(a+b); // ok const int
f(7); // ok const int
int a, b;
f(a); // ambiguous
f(a+b); // ambiguous
f(7); // ambiguous
int&
int a, b;
f(a); // ok int&
f(a+b); // ok const int &
f(7); // ok const int &
const int&
Jan-Feb 2016
31
void f(T1);
void f(T2);
Jan-Feb 2016
T1, T2
double
int
int a;
f(a); //
f(7); //
const int
int a;
f(a); //
f(7); //
int&
int a;
f(a); //
f(7); //
const int&
int a;
f(a); //
f(7); //
32
void f(T1);
void f(T2);
Jan-Feb 2016
T1, T2
double
int
int a;
f(a); // ok int
f(7); // ok int
const int
int a;
f(a); // ok const int
f(7); // ok const int
int&
int a;
f(a); // ok int&
f(7); // ok double
const int&
int a;
f(a); // ok const int&
f(7); // ok const int&
33
Function:
Prefix: max(a, b);
qsort(int[], int, int, void (*)(void*, void*));
Jan-Feb 2016
34
is equivalent to:
int operator+(int x, int y);
c = operator+(a, b);
Jan-Feb 2016
35
Jan-Feb 2016
36
Overload Operator+
#include <iostream>
using namespace std;
enum E {C0 = 0, C1 = 1, C2 = 2};
int main() {
E a = C1, b = C2;
int c = -1;
Output:
3
c = a + b;
cout << c << endl;
return 0;
}
Jan-Feb 2016
37
Overload Operator+
#include <iostream>
using namespace std;
int main() {
E a = C1, b = C2;
int c = -1;
return 0;
}
return (E) t;
}
Output:
0
Jan-Feb 2016
38
Examples of Resolution
(Conflict)
1. Promotion
enum e1 { a1, b1, c1 };
enum e2 { a2, b2, c2 =
0x80000000000 };
char *f(int);
char *f(unsigned int);
int main() {
f(a1); // Which f?
f(a2); // Which f?
}
Jan-Feb 2016
2. Standard Conversion
void print(int);
void print(char *);
void set (int *);
void set (const char *);
int main() {
print(0); // Which print?
set(0);
// Which set?
}
39
new/delete operators
In C++, the new and delete operators provide built-in
language support for dynamic memory allocation and deallocation.
int *pI = new int;
int *pI = new int(102); //new initializes!!
int *pArr = new int[4*num];
Arrays generally cannot be initialized.
const int *pI = new const int(100);
Array of constant cannot be created.
delete pI;
delete [] pArr;
new is polymorphic
new does more than malloc!
Jan-Feb 2016
40
Matching operators
malloc-free
new-delete
new[] delete[]
41
CLASS
Jan-Feb 2016
42
TOPICS
Class Members
Constructor & Destructor
Friends
Static Members
Struct & Union
Jan-Feb 2016
43
Class
C++ Class is an implementation of type
In C++, class is the only way to implement user
defined data types
A C++ class contains data members/attributes to
specify the state and operations/methods to specify
the behavior
Thus, classes in C++ are responsible to offer
needed data abstraction/encapsulation of Object
Oriented Programming
C++ Classes also provide means (through access
specifier) to enforce data hiding that separates
implementation from interface
Jan-Feb 2016
44
Class
A Class is defined by class keyword
Each member in a class has an access specifier
private accessible inside the definition of the
class
public accessible everywhere
Objects/instances of classes are to be created
statically or dynamically
Members can be accesses by . operator on the
object
The implicit this pointer holds the address of any
object.
this pointer is implicitly passed to methods.
Jan-Feb 2016
45
A Simple Class
class Employee {
public:
void setName (const char *x)
{ name = strdup(x); }
void setSalary (float y)
{ salary = y; }
char *getName ( )
{ return name; }
float getSalary ( )
{ return salary; }
private:
char *name;
float salary;
};
Jan-Feb 2016
int main ()
{
Employee e1; Employee *e2;
e2 = new Employee;
e1.setName("Amit");
e2->name = strdup("Ashis");
// Error
e1.setSalary(29100);
e2->setSalary(29100);
}
Re-look at
void setName (const char *x)
{ name = strdup(x); }
Whose name?
void setName (const char *x)
{ this->name = strdup(x); }
46
More on this
Type of this
X * const
DoublyLinkedNode::
append(DoublyLinkedNode *x) {
next = x;
x->prev = this;
}
47
Constructor Functions
Constructor functions:
are member functions with the same name
as the class
are automatically called when an object is
created, just after memory allocation
In case of auto/static variables, objects are created in
the stack/static Store when their definition is
encountered
Objects can be created in the Free store with a pointer
storing the address.
48
Constructor Functions
Constructor functions:
Constructors also allocate additional
memory space from the Free store (if)
required for the object
Must not have any return type even void
Default constructors are those constructors
which either do not have an argument or
have default arguments for all parameters
If users do not define any constructor then
the compiler provides a default constructor
Jan-Feb 2016
49
Jan-Feb 2016
50
Destructor Functions
Destructor function:
is a member function named ~ <class-name> (e.g. ~
String ( ) )
51
Copy Constructor
Copy constructor is a special
constructor which is used to initialize an
object with another object of the same
type.
Copy constructor of class X takes an
argument of type X&.
If the type of argument is X in stead of X&,
an infinite loop results.
Jan-Feb 2016
52
Copy Constructor
Situations where copy constructor is
used:
Actual parameter passing in call-by-value
Return Value passing
Initializing an object with an object of the
same type as shown in the following
example.
53
Jan-Feb 2016
54
int main()
{
String s1; //default constructor
len = 0;
}
char str[6];
strcpy(str, Hello);
len = strlen(s);
String s2(str);
strcpy(data, s);
void ~String() {
delete s4;
if (data != NULL)
delete s5;
delete [] data;
}
}
Jan-Feb 2016
55
Arrays
Using Default constructor while
creating an array of objects
String *pArrayOfString[2] =
{ new String(abc), new String(def) };
Jan-Feb 2016
56
int len;
}
Solution
Change the return type to String &
Jan-Feb 2016
57
Leak as
previous data of this is
not deleted.
58
Bug:
Self Assignment will cause problem
Solution:
Check the following condition and return if
false.
if (this != rhs) .
Jan-Feb 2016
59
Jan-Feb 2016
60
More On = Operator
Overloading
There is a system defined implementation of
assignment operator. In absence of user defined
assignment operator function, systems function is
used.
System defined function makes a shallow copy.
Some times shallow copying may be dangerous
61
Object Layout
Simplistically, an object
of a class must have
enough space to store all
members of that class.
No space is required per
object for storing function
pointers for the methods
declared in the class.
Jan-Feb 2016
A String Object
data
len
H e l l o \n
62
Members as Objects
Sometimes a class may have a data attribute
which is an object of a class.
Employee class may have a member name whose
type is String.
Jan-Feb 2016
63
Members as Objects
Initialization of member objects can be arranged
through the use of initializer lists
Initializer lists appear as a comma separated list
Jan-Feb 2016
64
65
Jan-Feb 2016
class X {
private:
int ipriv;
public:
int ipub;
int f() const;
};
66
Friend Functions
Friend functions
are declared in one or more classes
have access to the private members of
those classes
are distinguished from members with
the keyword friend
are not called with an invoking object
of those classes
Jan-Feb 2016
67
Jan-Feb 2016
68
Jan-Feb 2016
69
Jan-Feb 2016
class Matrix;
class Vector {
public:
void Vector(int n);
Vector prod(Matrix *pM);
int elements[10];
int n;
} ;
class Matrix {
public:
void Matrix(int m, int n);
friend Vector Vector::prod(Matrix *pM);
private:
int elements[10][10];
int m, n;
} ;
70
Static Data
A static data member is
shared by all the objects
of a class.
Static data member may
be public or private.
Static data member must
be initialized in a source
file.
It can be accessed
Jan-Feb 2016
X.h
--class X {
public:
static int count; // This is a
declaration
X() { count++; }
}
X.cxx
----#include X.h
int X::count = 0; //Definition & Initialization
int main()
{
X a, b, c;
printf(%d %d %d %d\n, X::count, a.count,
b.count, c.count);
}
void ListNode::print() {
ListNode *x;
x = ListNode::first;
while (x != NULL)
{
printf(%d , x->data);
x = x->next;
}
printf(\n);
}
int main() {
ListNode x(5);
ListNode x(7);
ListNode x(8);
x.print();
}
73
Jan-Feb 2016
X.cxx
#include X.hxx
void X::f()
{
X::g();
}
OPERATOR OVERLOADING
Jan-Feb 2016
75
Overloading Operators
Semantics of an operator is
represented by a function named
operator op, where op is an operator
symbol (+,*, - , [ ], etc. )
These functions can either be
implemented as global friend functions
and/or methods.
Jan-Feb 2016
76
Overloading Operators
Example
Let + denote concatenation for Strings.
s1 + s2 denote concatenation of strings s1
and s2.
An expression of the form s1+s2 is
converted to s1.operator+(s2) if there is a
function named operator+ defined in the
class String.
s1+s2 is also equivalent to operator+(s1,
s2) if a global function named operator+ is
properly defined; typically such global
functions are friends to the class String.
Jan-Feb 2016
77
Example of overloading
operator +
/ * string .h * /
const int max_string_length = 128 ;
class String {
public :
String operator + (char *text) ;
String operator + (String &s1) ;
String (char *data);
String () { data = NULL; len = 0; }
private :
char *data;
int len;
};
Jan-Feb 2016
78
Problem: Returning
reference to a local
object. The code fails.
Jan-Feb 2016
Who deletes?
The caller.
What about the following
use?
Integer a(1), b(2), c(3),
d(3);
Integer e =
a*b*c*d;
79
Jan-Feb 2016
80
Jan-Feb 2016
81
Friends vs Methods
Members are better in terms of restriction of
scope which results in efficient searching for
best function to resolve overloading.
Members will not help if the left hand side of the
operator is not of the class type.
String s1 = abc + s2; // may be wrong
82
83
Jan-Feb 2016
String s1 = Hello;
cout << s[0];
// fine
s[0] = x;
// fine
const String cs = World;
cout << s[0];
// fine
s[0] = x;
// Error!!!
84
85
INHERITANCE
Jan-Feb 2016
86
Topics
Fundamentals of Inheritance
protected Access Specifier
Initialization
Virtual Functions
Jan-Feb 2016
87
Reusability
Reuse an already tried and tested code
Advantages:
Reduces cost & development time.
Improves quality
Jan-Feb 2016
88
89
90
91
protected Members
private data members of the base class
cannot be directly accessed by the
methods of the derived class.
However, it is important for the derived
class to have more accessibility to the
members of the base class than other
classes or functions.
If a member is protected then it is
directly accessible to the methods of the
derived class.
Jan-Feb 2016
92
Syntax of Inheritance
An example
class Employee {
protected:
float basic;
long id;
public:
Employee(long id);
float getSalary();
};
class Manager : public Employee {
protected:
Employee *supervised[10];
int numberOfPeopleManaged;
public:
Manager(Id, n);
float getSalary();
void printSupervisedEmployeeId();
}
Jan-Feb 2016
93
Jan-Feb 2016
94
Jan-Feb 2016
95
96
Casting
Derived class pointer can be implicitly
cast to a base class pointer
Manager m;
Employee *e = &m; // Employee *e = (Employee *)(&m);
Jan-Feb 2016
97
Casting
A Base class pointer cannot be implicitly
cast to a derived class pointer
Manager *pM; pM = e; //error
pM = (Manager *)e; //ok
Down casting may be dangerous
Jan-Feb 2016
98
Jan-Feb 2016
99
Jan-Feb 2016
100
Virtual Functions
In C++, dynamic binding is made
possible only for pointer & reference
data types and for methods that are
declared as virtual in the base class.
If a method is declared as virtual, it
can be overridden in the derived class.
If a method is not virtual and it is redefined in the derived class then the
latter definition hides the former one.
Jan-Feb 2016
101
class Y: public X{
public:
public:
};
};
main() {
Y a;
int i, j , k, m;
Output will be 2 4 6 6
X *b = &a;
i = b->f(); j = a.f();
k = b->g(); m = a.g();
printf(%d %d %d %d\n, i, j, k, m);
}
Jan-Feb 2016
102
Redefining a Non-Virtual
Function
Simply do not do that.
class X() {
class Y : public X {
protected:
protected:
void f();
};
void f();
};
int main() {
Y y1;
Y *pY; X *pX;
pX = &y1;
pX->f(); // f as defined in X will be called
pY = &y1;
pY->f(); // f as defined in Y will be called
}
Jan-Feb 2016
103
Jan-Feb 2016
Actual definition of
the virtual function
104
Abstract Class
Pure Virtual Function
A virtual function may be assigned to NULL meaning that
this function is declared but not defined in a class.
Definition of such a class is incomplete.
105
Virtual Destructor
Constructors cannot be virtual
For a base class which has been derived from,
the destructor must be declared virtual.
Occasionally we create a derived object and store
it using a pointer to Base class such as
Base *pBase = new Derived(/*arguments*/);
106
Inheritance Example:
Polymorphic Array
Consider an abstract base class Shape which
contains a pure virtual function CalculateArea.
Suppose three classes Triangle, Rectangle and
Circle derived from Shape.
Consider a main function that creates different
Shape objects and store them in an array.
If in a for loop the function calculateArea is
called on all objects in the array, we see
dynamic binding in use.
Jan-Feb 2016
107
public:
0;
private:
Point centre;
double radius;
};
Circle(double x_centre,
double y_centre,
private:
double r);,
Point a, b, c;
public:
double calculateArea();
};
public:
double calculateArea();
};
Jan-Feb 2016
108
int main() {
int n = getInput(pArr);
scanf(%d, &i);
switch (i) {
double area =
case 0: break;
Shape[i]->calculateArea();
case 1:
scanf(%f%f%f%f%f%f, &x_a,
break;
..
}
}
}
Jan-Feb 2016
109
Inheritance: Benefits
Code Sharing/Reuse
Consistency of Interface
Construction of Software Components
Rapid Prototyping
Information Hiding
Jan-Feb 2016
110
Inheritance: Cost
Execution Speed
Program Size
Message Passing Overhead
Program Complexity
Jan-Feb 2016
111
Inheritance: Limitations
operator= cannot be inherited
Can be used to assign objects of the same
type only
112
Inheritance Notes
Constructors cannot be virtual
Calling a virtual function from within a
constructor does not have the desired effect.
The following code is buggy. Tell why.
void f(Base *b) {
int main() {
b[0].f(); b[1].f();
Derived d[10];
f(d);
}
113
class Y : public X {
protected:
protected:
int main() {
Y y1;
Y *pY; X *pX;
pX = &y1;
pX->f(); // f with value of i as 10 will be called
pY = &y1;
pY->f(); // f with value of i as 20 will be called
}
Jan-Feb 2016
114
Is an Ostrich a Bird
Suppose there is a base class Bird
a virtual method fly returns altitude > 0.
115
Is a Circle an Ellipse?
Circle is a special type of ellipse.
Let Circle be derived from Ellipse.
Suppose that Ellipse has a method
setSize(x,y).
Also suppose that there is a function sample as
defined below.
sample (Ellipse &e) { e. setSize(10,20); . }
If sample is called on a circle, strange things
happen!
Subset is not substitutable!!
Jan-Feb 2016
116
117
Multi-level Inheritance
Suppose that C is derived from B and B is
derived from A.
Suppose that a method, f, in A is virtual.
If f is redefined in B then f is virtual even if
the keyword virtual does not precede the
declaration/definition in the derived class.
It is advisable to explicitly write virtual in
front of the definition of f in B as, otherwise,
an implementer of C may think that f is not a
virtual method.
Jan-Feb 2016
118
Jan-Feb 2016
119
private Inheritance
If B is privately derived from A then private,
protected and public members of A become
private members of B. However, private
members of A are not directly accessible to B.
Thus, even if C is publicly derived from B then
no member of A is accessible to C.
Functions which may access members of A in B
are
Methods of class B
Friend functions of class B.
Jan-Feb 2016
120
protected Inheritance
If B is protectedly derived from A then,
protected and public members of A become
protected members of B. However, private
members of A remain private in B and are not
directly accessible to B.
Functions which may access members of A in B
are
Methods of class B
Friend functions of class B.
Methods in classes publicly derived from B
Friend functions of classes publicly derived from B
Jan-Feb 2016
121
122
TYPE CASTING
Jan-Feb 2016
123
Type Casting
Why casting?
Casts are used to convert the type of an object,
expression, function argument, or return value to
that of another type.
Explicit conversions.
type is needed for an expression that cannot be
obtained through an implicit conversion
more than one standard conversion creates an
ambiguous situation
Jan-Feb 2016
124
Type Casting
To perform a type cast, the compiler
allocates temporary storage
Initializes temporary with value being cast
float f (int i,int j) {
return (float ) i / j;
}
// compiler generates:
float f (int i, int j) {
float temp_I = i, temp_j = j;
return temp_i / temp_j;
}
Jan-Feb 2016
125
126
127
128
Ambiguities: Example
Overuse of such
casting may lead to
ambiguities as
illustrated in the
following example
/* ambig.cpp */
#include string.h
class example {
public:
example(const char *) { } ;
};
void
Jan-Feb 2016
129
Ambiguity: Example
class B;
class A {
public:
A (const B &);
...
};
class B {
public:
operator A () const;
};
void f(const A &);
B b;
f(b); //Error - Ambiguous
Jan-Feb 2016
130
Jan-Feb 2016
131
Avoiding Ambiguities
const int max_string_length = 128;
class String {
public:
String ( ) ;
String (const String & ) ;
String (const char *);
~ String ( ) ;
String & operator = (const String &
);
const char *as_char_pointer ( )
const;
int length ( ) const;
int read ( );
void print ( ) const;
...
private:
char text [max_string_length+1];
};
Jan-Feb 2016
134
C++ casts
There are four cast operators in C++
const_cast
static_cast
reinterpret_cast
dynamic_cast
Jan-Feb 2016
135
Jan-Feb 2016
136
const_cast operator
Syntax:
Jan-Feb 2016
137
int main() {
CCTest X;
X.setNumber( 8 );
X.printNumber();
}
Usage of const
The example of the previous slide is not
the best usage of const.
The member number should be mutable
instead.
139
Jan-Feb 2016
140
static_cast operator
Syntax:
static_cast < type-id > ( expression )
Jan-Feb 2016
141
static_cast operator
In general, a complete type can be converted
to another type so long as some conversion
sequence is provided by the language.
may also use static_cast to convert any
expression to a void, in which case the value of
the expression is discarded.
It cannot change the const-ness of an
expression.
Jan-Feb 2016
142
static_cast: Example
Example:
class B { ... };
class D:public B { ... };
void f(B* pb, D* pd){
D* pd2 =
static_cast<D*>(pb);
// not safe, pb may point to
just B
B* pb2 = static_cast<B*>(pd);
// safe conversion
...
}.
Jan-Feb 2016
143
Jan-Feb 2016
144
reinterpret_cast operator
Syntax:
reinterpret_cast < type-id > ( expression )
145
reinterpret_cast operator
The result of a reinterpret_cast cannot safely be used for
anything other than being cast back to its original type.
Other uses are, at best, non-portable.
The reinterpret_cast operator cannot cast away the
const, volatile attributes.
One practical use of reinterpret_cast is in a hash
function, which maps a value to an index in such a way
that two distinct values rarely end up with the same
index.
Reinterpret_cast should rarely be used in a C++
program
Jan-Feb 2016
146
reinterpret_cast: Example
Example
#include <iostream>
unsigned short Hash( void *p ){
// Returns a hash code based on an
address
unsigned int val =
reinterpret_cast<unsigned int>( p
);
return ( unsigned short )( val ^ (val
>> 16));
}
int main(){
int a[20];
for ( int i = 0; i < 20; i++ )
cout << Hash( a + i ) << endl;
}
Jan-Feb 2016
The reinterpret_cast
allows the pointer to be
treated as an integral
type. The result is then
bit-shifted and XORed
with itself to produce a
unique index (unique to
a high degree of
probability). The index is
then truncated by a
standard C-style cast to
the return type of the
function.
147
Usage of casts
class A { public: virtual ~A(); };
class B : private virtual A { };
class C : public A { };
class D : public B, public C { };
A a1; B b1; C c1; D d1;
const A a2;
const A& ra1 = a1;
const A& ra2 = a2;
char c;
A *pa = (A *)&ra1;
Use const_cast
B * pb = (B*)&c1;
Use reinterpret_cast
A *pa = (A*)&a2;
Cannot be expressed
in a new-style cast.
Jan-Feb 2016
148
Jan-Feb 2016
149
type_info class
The type_info class describes type information
generated within the program by the compiler. The
entire definition of this class is implementation
dependent but the following features of this class is
standardized.
Objects of this class effectively store a pointer to a
name for the type. The type_info class also stores an
encoded value suitable for comparing two types for
equality or collating order.
The operators == and != are overloaded and can
be used to compare for equality and inequality with
other type_info objects, respectively.
Jan-Feb 2016
150
type_info class
Features of type_info class (contd):
The name member function returns a const char*
to a null-terminated string representing the humanreadable name of the type. The memory pointed to is
cached and should never be directly deallocated.
Jan-Feb 2016
151
typeid operator
Syntax:
typeid( type-id )
OR
typeid(expression)
152
typeid operator
When the operand of typeid is of a nonpolymorphic class type, the result is the type of
the operand not the type of the underlying
object.
type-id may be used with operands of built-in
types.
Jan-Feb 2016
153
typeid:Example
The expression usually
points to a polymorphic
type (a class with virtual
functions).
The pointer must be dereferenced so that the
object it points to is used.
Without de-referencing the
pointer, the result will be
the type_info for the
pointer, not pointee
Example
int main(){
Derived* pd = new Derived;
Base* pb = pd;
cout << typeid( pb ).name() << endl;
//prints "class Base *
cout << typeid( *pb ).name() <<
endl; //prints "class Derived"
cout << typeid( pd ).name() << endl;
//prints "class Derived *"
cout << typeid( *pd ).name() <<
endl; //prints "class Derived"
delete pd;
}
#include <iostream>
#include <typeinfo.h>
class Base {
public: virtual void vvfunc() {} }
class Derived : public Base {};
Jan-Feb 2016
154
dynamic_cast operator
Syntax:
dynamic_cast<typeid> (expression)
The expression
dynamic_cast<typeid>( expression)
converts the
operand expression
to an object of type
type-id.
It is used for downcasting.
Jan-Feb 2016
Example
class B { ... };
class C : public B { ... };
class D : public C { ... };
void f(D* pd){
C* pc = dynamic_cast<C*>(pd);
// ok: C is a direct base class, pc points to
C subobject of pd
B* pb = dynamic_cast<B*>(pd);
// ok: B is an indirect base class , pb
points to B subobject of pd
...
}
155
dynamic_cast: Example
Example:
class B { ... };
class D : public B { ... };
void f(){
B* pb = new D;
// unclear but ok
B* pb2 = new B;
D* pd = dynamic_cast<D*>(pb);
// ok: pb actually points to a D
...
D* pd2 = dynamic_cast<D*>(pb2); // pb2 points to a B not a D the cast is bad
so pd2 is NULL
...
}
Jan-Feb 2016
156
dynamic_cast
If dynamic_cast to a pointer type fails, the result of the
dynamic_cast is null; if dynamic_cast to a reference type
fails, an exception is thrown.
dynamic_cast is performed at run-time.
dynamic_cast can be used only for pointer or reference
types to navigate a class hierarchy. The dynamic_cast
operator can be used to cast from a derived class pointer
to a base class pointer, cast a derived class pointer to
another derived (sibling) class pointer, or cast a base
class pointer to a derived class pointer. Each of these
conversions may also be applied to references.
Jan-Feb 2016
157
dynamic_cast
dynamic_cast operator cannot be used for built-in types.
All of the derived-to-base conversions are performed
using the static (compile-time) type information. These
conversions may, therefore, be performed on both nonpolymorphic and polymorphic types. These conversions
will produce the same result if they are converted using a
static_cast. However, even these results may be wrong in
the presence of multiple inheritance.
dynamic_cast is strongly recommended to be applied on
polymorphic types.
Jan-Feb 2016
158
Cost of dynamic_cast
The pointer to the type_info object of a class is
stored in the vtbl array of the class.
Thus, the space cost for RTTI is an additional
entry in each class vtbl plus the cost of storage
for the type_info object for each class.
Size of the objects do not increase for RTTI
operations.
Cost of RTTI at run time is similar to the cost
of calling a virtual function; cost of calling a
virtual function is the same as the cost of
calling a function through a function pointer.
Jan-Feb 2016
159
EXCEPTIONS
Jan-Feb 2016
160
Topics
Basic Concept of Exceptions
try-catch block in C++
Semantics of throw
Jan-Feb 2016
161
by output parameter
normal and abnormal control flow
tend to mix
Reusing code for error handling is
difficult.
Jan-Feb 2016
162
163
Jan-Feb 2016
A Calculator need to
handle divide by zero
Could set value to NAN
But, program would need
to check for special value
(and might ignore)
Could return 1
Again program could
ignore
Might be a valid return
value
164
Jan-Feb 2016
165
166
private:
int i = 0;
int dividend;
Calculator c;
public:
try {
print() {
c.divide (0);
DivideByZero(int d) { dividend = d; }
ex.print();
};
return 1;
}
return 0;
}
value /= i;
return value;
}
Jan-Feb 2016
167
int dividend;
public: print() {
Calculator c;
try {
c.divide (0);
cout <<
c.getValue ();
DivideByZero(int d)
{ dividend = d; }
};
ex.print();
int Calculator::divide(int i)
throws DivideByZero {
return 1;
}
if (i ==0)
throw DivideByZero(value);
return 0;
}
value /= i;
return value;
}
Jan-Feb 2016
168
Details of throw
Normal program control flow is halted
At the point where an exception is thrown
Jan-Feb 2016
169
Jan-Feb 2016
170
Exception Specifications
// can throw anything
void
Calculator::subtract
(int i);
// promises not to throw
void
Calculator::add
(int i) throw ();
// promises to only throw int
void
Calculator::divide
Comma separated
171
Exception Specifications
// can throw anything
void
Calculator::subtract
(int i);
Comma separated
172
Stack Frame
automatic variables
parameters
previous frame pointer
return address
Jan-Feb 2016
int i = 0;
Calculator c;
try {
c.divide (0);
cout <<
c.get_value ();
}
catch (int) {
return 1;
Jan-Feb 2016
}
return 0;
value_
main
argc
argv
174
Calculator c;
try {
c.divide (0);
cout <<
c.get_value ();
}
catch (int) {
return 1;
}
return 0;
}
Jan-Feb 2016
value_
main
argc
argv
175
c.get_value ();
catch (int) {
Calculator c;
Calculator::
Calculator( )
this
return 1;
}
return 0;
}
Jan-Feb 2016
value_
main
argc
argv
176
: value_ (0)
{}
void
Calculator::divide (int i) throw (int)
{
if (i == 0) {
throw i;
Calculator::
Calculator()
this
} else {
value_ /= i;
}
cout << value_;
}
Jan-Feb 2016
value_
main
argc
argv
177
void
Calculator::divide (int i) throw
(int) {
if (i == 0) {
throw i;
} else {
value_ /= i;
}
cout << value_;
main
value_
argc
argv
}
Jan-Feb 2016
178
int i = 0;
Calculator c;
try {
c.divide (0);
cout <<
void Calculator::
divide (int )
c.get_value ();
this
}
catch (int) {
return 1;
}
return 0;
value_
main
argc
argv
}
Jan-Feb 2016
179
void
Calculator::divide (int i) throw (int)
{
if (i == 0) {
throw i;
} else {
value_ /= i;
}
cout << value_;
}
void Calculator::
Calculator (int )
this
i
i
value_
main
argc
Jan-Feb 2016
argv
180
Jan-Feb 2016
value_
main
argc
argv
181
{
int i = 0;
Calculator c;
try
{
c.divide (0);
cout << c.get_value ();
}
catch (int)
{
return 1;
}
return 0;
}
value_
main
argc
Jan-Feb 2016
argv
182
More on catch
try {
// can throw an exception
}
catch (Derived &d) {
// ...
}
catch (Base &b) {
// ...
}
catch (...) // catch all...
{
// ...
}
Jan-Feb 2016
Jan-Feb 2016
Notice catch-by-reference
for user defined types
More efficient
More correct
TEMPLATES
Jan-Feb 2016
185
What is a Template?
Templates are specifications of a
collection of functions or classes which
are parameterized by types.
Examples:
Function search, min etc..
The basic algorithms in these functions are the same
independent of types.
But, we need to write different versions of these
functions for strong type checking in C++.
186
Template instantiation
Jan-Feb 2016
187
Example
#include <iostream>
#include <string> using namespace std;
template <typename T>
inline T const& Max (T const& a, T const& b)
{ return a < b ? b:a; }
int main () {
int i = 39; int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5; double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello"; string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
Jan-Feb 2016
188
Example
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept> using namespace std;
template <class T>
class Stack {
private: vector<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
T top() const; // return top element
bool empty() const { // return true if empty.
return elems.empty(); }
};
Jan-Feb 2016
189
Parameterized Functions
A function template
describes how a function should be built
supplies the definition of the function using some
arbitrary types, (as place holders),
a parameterized definition
can be considered the definition for a set of overloaded
versions of a function
is identified by the keyword template
followed by parameter identifiers
enclosed between < and > delimiters
noting they are
Jan-Feb 2016
191
typename
The key words class and typename have
almost the same meaning in a template
parameter
typename is also used to tell the compiler that
an expression is a type expression
template <class T> f (T x) {
T::name * p; // Is this a pointer declaration or multiplication?
}
template <class T> f (T x) {
typename T::name * p; // Is this a pointer declaration or
multiplication?
}
Jan-Feb 2016
192
Jan-Feb 2016
193
Jan-Feb 2016
194
195
Jan-Feb 2016
196
Jan-Feb 2016
197
Jan-Feb 2016
198
Parameterized Class
A class template
describes how a class should be built
Supplies the class description and the
definition of the member functions using some
arbitrary type name, (as a place holder).
is a parameterized type with
parameterized member functions
Jan-Feb 2016
199
Parameterized Class
can be considered the definition for an
unbounded set of class types
is identified by the keyword template
followed by parameter identifiers
enclosed between < and > delimiters
noting they are class, (i.e. type),
parameters
is often used for container classes
Jan-Feb 2016
200
Parameter Requirements
Parameter Types
may be of any type, (including user defined
types)
may be parameterized types, (i.e. templates)
MUST
Jan-Feb 2016
201
202
203
Separation Model
Use keyword export in front of definition.
Jan-Feb 2016
Template specialization
Allows to make specific implementation when
pattern is of determined type.
The syntax is
template<> class XXX<Type> {..}
205
Jan-Feb 2016
template<class T>
void Set<T> : : add (const T &val)
{
if (items.find (val) ) return;
items.put (val) ;
}
template<class T>
int Set<T> : : length ( )
{
return items.length ( ) ;
}
template<class T>
int Set<T> ::find (const T &val)
{
return (int) items.find(val);
}
207
Template Inheritance: A
Derived Template
/* boundset.h */
#include set.h
template<class T>
class BoundSet : public Set<T>
public:
BoundSet (const T &lower,
const T &upper);
void add(const T &val);
private:
T min;
T max;
};
Jan-Feb 2016
template<class T>
BoundSet<T>:: BoundSet (const T
&lower, const T &upper)
: min (lower), max (upper)
{
}
template<class T>
void BoundSet<T> : :add(const T
&val)
{
if (find (val) ) return;
if ( (val <= max) && (val
>= min) )
Set<T>: : add
(val) ;
}
208
Jan-Feb 2016
209
Inheritance vs Templates
Inheritance : helps in reusing object code
Templates : helps in reusing source-code
object code size of template code is therefore much
less.
Compiler view
Constructor of objects containing virtual functions
must initialize the vptr table.
Template class knows the type of the class at
compile-time instead of having to determine it at
run-time (as in case of virtual function usage)
Jan-Feb 2016
210
Inheritance vs Templates:
Example
Implement the following command.
# ECHO infile outfile
main() {
(argc > 2 ? ofstream (argv[2]
,ios::out) : cout) <<
(argc > 1 ? ifstream (argv[1],
ios::in) : cin)
.rdbuf();
}
main()
{
fstream in, out;
if (argc > 1) in.open(argv[1],
ios::in);
if (argc > 2) out.open(argv[2],
ios::out);
Process(in.is_open() ? in
: cin,
out.is_open() ? out :
cout);
}
Jan-Feb 2016
211
Inheritance vs Templates:
Solution
template<typename In, typename
out>
void process(In& in, Out& out)
{
// out << in.rdbuf();
}
Requirement:
Another Example
A collection of classes is required for
Stack: for ints , strings, floats etc.
213
Thank You
1
2
3
4
5
6
10
8
11
12
38
9
17
18
15
13
20
14
=
=
=
=
=
=
+
=
+
+
+
+
+
+
C
Java
Objective-C
C++
C#
PHP
JavaScript
Python
Visual Basic .NET
Perl
Visual Basic
R
Transact-SQL
PL/SQL
Pascal
Delphi/Object Pascal
Swift
Ruby
F#
MATLAB
17.59%
14.96%
9.13%
6.10%
4.33%
2.75%
2.43%
2.29%
2.24%
1.83%
1.80%
1.63%
1.47%
1.33%
1.17%
1.12%
1.07%
0.98%
0.89%
0.87%
-0.30%
-2.35%
-1.07%
-2.16%
-1.29%
-2.53%
0.58%
0.08%
0.55%
0.75%
1.80%
1.38%
-0.40%
0.73%
0.58%
0.43%
1.06%
0.05%
0.32%
0.16%
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Jan-Feb 2016
215
Ratings Change
1
1
=
C
17.87% 0.02%
2
2
=
Java
16.50% -0.92%
3
3
=
Objective-C
11.10% 0.82%
4
4
=
C++
7.55% -1.59%
5
5
=
C#
5.86% -0.34%
6
6
=
PHP
4.63% -0.92%
7
7
=
(Visual) Basic
2.99% -1.76%
8
8
=
Python
2.40% -1.77%
9
10
+
JavaScript
1.57% -0.41%
10
22
+
Transact-SQL
1.56% 0.98%
11
12
+
Visual Basic .NET
1.56% 0.52%
12
11
Ruby
1.08% -0.69%
13
9
Perl
0.92% -1.35%
14
14
=
Pascal
0.78% -0.15%
15
17
+
MATLAB
0.78% 0.14%
16
45
+
F#
0.72% 0.53%
17
21
+
PL/SQL
0.63% 0.05%
18
35
+
D
0.63% 0.33%
19
13
Lisp
0.60% -0.35%
20
15
Delphi/Object Pascal
0.60% -0.32%
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Jan-Feb 2016
216
Jan-Feb 2016
217