Sie sind auf Seite 1von 63

Programming in C++

Slide: 1 Matangini Chattopadhyay


Topics

Procedural Enhancements in C++ over C


Classes
Overloading

Slide: 2 Matangini Chattopadhyay


Object Oriented Programming in C++
Major Procedural Feature Enhancements in C++ Over
ANSI C

Slide: 3 Matangini Chattopadhyay


TOPICS

Const-ness
Reference Data Type
Inline Functions
Default Function Parameters
Function Overloading & Resolution
Dynamic Memory Allocation

Slide: 4 Matangini Chattopadhyay


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.
Pointer to a non-constant object can not point to a const
object;
const double d = 5.6;
double *p = &d; //error
Pointer to a constant object vs. constant pointer to an
object.
const double * pConstantObject;
double * const *pConstantPointer;

Slide: 5 Matangini Chattopadhyay


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;

Slide: 6 Matangini Chattopadhyay


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
Often used as function parameters :
called function can change actual argument
faster than call-by-value for large objects

Slide: 7 Matangini Chattopadhyay


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
All operations on a reference actually work on the
referent.
Slide: 8 Matangini Chattopadhyay
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

Slide: 9 Matangini Chattopadhyay


Returning a Reference
#include <iostream.h.>

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;
}

Slide: 10 Matangini Chattopadhyay


Pointers vs. References

Pointers can point to NULL whereas References


cannot. There is nothing defined as NULL
Reference.
Pointers can point to different variables at
different times whereas for a reference, its
referent is fixed.
References make code faster since, unlike
pointers, checks for NULL are not required.
Reference refers to an address but does not
store that address. Pointer does.

Slide: 11 Matangini Chattopadhyay


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

Code size tend to increase

Typical Use:
Small code re-use
Slide: 12 Matangini Chattopadhyay
Inline Functions
Inline functions act like functions
They can be class members
Type checking is performed
They can be overloaded
They obey normal parameter passing rules
But they are implemented like macros
Code is substituted inline, not called
Use is faster than calling a function
Use may take more space
They are defined in .h files, not in .c/.cxx files

Slide: 13 Matangini Chattopadhyay


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.

Slide: 14 Matangini Chattopadhyay


Default Function Arguments
Default arguments are appropriate argument
value of a parameter for a majority of cases.
Default arguments can be supplied to one or
more parameters.
Default arguments may be expressions also.
All parameters to the right of a parameter with
default argument must have default arguments.
Default arguments cannot be re-defined.
Default parameters should be supplied only in a
header file and not in the definition of a function.
Slide: 15 Matangini Chattopadhyay
Default Arguments: Example
Following are some examples of functions with default
arguments.
Void ff (int, float = 0.0, char *); // Error
Void ff2(int, float = 0, char *=NULL); // OK
Void ff2(int, float = 1, char *= NULL); // Error Redefinition
Assume that ff.h contains the following declaration
ff(int, float, char = a);
Wrong example:
#include ff.h
ff(int i, float f = 0.0, char ch = a); //Error
However, the following are correct.
#include <ff.h>
ff(int i, float f = 0.0, char ch); //OK
ff(int i = 0, float f, char ch); //OK

Slide: 16 Matangini Chattopadhyay


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 re-declare.
Overloading allows static polymorphism

Slide: 17 Matangini Chattopadhyay


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)
Exact Match
Promotion
Standard type conversion
User defined type conversion

Slide: 18 Matangini Chattopadhyay


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

Slide: 19 Matangini Chattopadhyay


Promotion & Conversion
Examples of Promotion
char to int; float to double
enum to int/long/unsigned int/
bool to int
Examples of Standard Conversion
integral conversion
floating point conversion
floating point Integral conversion
The above 3 may be dangerous!
pointer conversion
bool conversion

Slide: 20 Matangini Chattopadhyay


Examples of Resolution
1. Promotion 3. Conversion Sequence
enum e1 { a1, b1, c1 }; int arr[3];
enum e2 { a2, b2, c2 = 0x80000000000 }; void putValues(const int *);
int main()
char *f(int); char *f(unsigned int);
{
int main()
{ putValues(arr);
f(a1); //Which f? }
f(a2); //Which f?
}

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?
}

Slide: 21 Matangini Chattopadhyay


new/delete operators
In C++, the new and delete operators provide built-in language
support for dynamic memory allocation and de-allocation.
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!

Slide: 22 Matangini Chattopadhyay


new/delete & malloc/free

All C++ implementations also permit use of malloc and


free routines.
Do not free the space created by new.
Do not delete the space created by malloc
Results of the above two operations is memory corruption.
Matching operators
malloc-free
new-delete
new[] delete []
It is a good idea to use only new and delete in a C++
program.

Slide: 23 Matangini Chattopadhyay


Object Oriented Programming in C++
Classes

Slide: 24 Matangini Chattopadhyay


TOPICS

Class Members
Constructor & Destructor
Friends
Static Members
Struct & Union

Slide: 25 Matangini Chattopadhyay


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.

Slide: 26 Matangini Chattopadhyay


Class
A Class is defined by class keyword.
Each member in a class has an access specifier.
private these members are accessible inside the definition of
the class.
public these members are 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.

Slide: 27 Matangini Chattopadhyay


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;
};

int main ()
{
Employee e1; Employee *e2;
e2 = new Employee;
e1.setName(Amit); e2->name = strdup(Ashis"); // Error
e2.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); }

Slide: 28 Matangini Chattopadhyay


More on this
Type of this
X * const
Necessity of this to the programmer
Distinguishing data member from non-member variable
Explicit Use
class DoublyLinkedNode DoublyLinkedNode::append(DoublyLinkedNode *x)
{ {
DoublyLinkedNode *prev, *next; next = x;
int data; x->prev = this;
public: }
void append(DoublyLinkedNode *x);
}

Slide: 29 Matangini Chattopadhyay


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.
allow the class to initialise the state of an object
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.

Slide: 30 Matangini Chattopadhyay


Additional Constructor Functions
Constructor function can be overloaded
Constructor functions can be directly called to
create anonymous objects
Calling a constructor from a constructor does
not have the desired effect.
If there is at least one definition of constructor
but no default constructor then the following
statements are incorrect
X a;
X *pX = new X();

Slide: 31 Matangini Chattopadhyay


Destructor Functions
Destructor function:
is a member function named ~ <class-name> (e.g. ~ String ( ) )

is automatically called when an object is destroyed, just before


memory is freed
For auto variables when the variable goes out of scope
For objects created in the Free store, destructor is called after delete or
delete[] is explicitly invoked by the programmer.

must not have any argument or return value

If destructor is not called then there could be memory


leaks for objects which calls new in the constructor.

Slide: 32 Matangini Chattopadhyay


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.
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.
The compiler provides a default implementation of the copy
constructor.

Slide: 33 Matangini Chattopadhyay


A Sample Class : String
class String {
public:
String();
String(const String&); // Copy Constructor
String(const char *);
~ String();
int length();
int read();
void print();
private:
char *data;
int len;
}

Slide: 34 Matangini Chattopadhyay


Class String::Constructor & Destructor
String::String() int main()
{ {
data = NULL; String s1; //default constructor
len = 0; String s11(); //Error
} String s1(test);
char str[6];
String::String(const char *s) strcpy(str, Hello);
{ String s2(str);
data = new char[strlen(s)+1];
String s3(s2); //Copy Constructor
len = strlen(s);
String s4 = new String(one);
strcpy(data, s);
String s5 = new String();
}
delete s4;
void ~String() delete s5;
{ }
if (data != NULL)
delete [] data;
}

Slide: 35 Matangini Chattopadhyay


Arrays
Using Default constructor while creating an
array of objects
String arrayOfString[100]; // 100 objects created using the default constructor

Using specialized constructor while creating an


array of objects.
String arrayOfString[2] = { String(abc), String(def) };

Using different constructor for creating array


objects dynamically.
String *pArrayOfString[2] = { new String(abc), new String(def) };

Slide: 36 Matangini Chattopadhyay


Object Layout
Simplistically, an object
A String Object
of a class must have
enough space to store all
members of that class.
No space is required per data
object for storing len
function pointers for the
methods declared in the
class.
Methods on objects are H e l l o \n
translated by the compiler
to C-like function calls by
passing this pointer.

Slide: 37 Matangini Chattopadhyay


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.
When an Employee object is initialized then name must also be
initialized.
Initialization of member objects can be arranged through the use of
initializer lists
Initializer lists appear as a comma separated list
following a colon, after a constructors parameters
and before the constructor definition
where each list item is a named member object followed by its initializer value in
parenthesis
Initializer lists are required for a member object that must be passed initial
arguments for construction
Initializer lists are required for const members and reference members

Slide: 38 Matangini Chattopadhyay


Class Member: Notes
It is always a good idea to define data members as private.
Composition through objects are preferred over Composition
through pointers
Saves time and life cycle management
Not possible in a number of situations
Contained object is shared by many containers.
Contained object may not always be present.

Methods should not return non-const reference or pointer to


less accessible data
Defeats basic data hiding philosophy.
May also lead to stunning consequences.

Slide: 39 Matangini Chattopadhyay


Const Member Functions
Constant Member Functions class X {
private:
are not allowed to change the int ipriv;
state of the object on which public:
int ipub;
they are invoked. int f() const;
};
Const Functions are declared
with keyword const following int X::f() const

member function parameter {


int temp;
list. temp = ipriv + ipub; //accessing members OK
ipriv += temp; // cannot modify any member
const must also be present at ipub -= temp; // cannot modify any member
the definition. }

Type of this pointer passed to


a const function is
const X* const this

Slide: 40 Matangini Chattopadhyay


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

Slide: 41 Matangini Chattopadhyay


Friend Functions: Example
class String { String concat(String *left, String *right)
public : {
String(); String both[left->len + right->len + 1];
String(const char *);
strcpy(both.data, left->data);
String(int len);
strcat(both.data, right-> data) ;
friend String concat(String *, String *)
return both;
friend String concat(String *, char *);
friend String concat(char *, String *); }

private :
char *data; String concat(char *left, String *right)
int len; {
} ; String both[strlen(left) + right->len + 1];
strcpy(both.data, left);
String::String(int len)
strcat(both.data, right->data);
{
return both;
this->len = len;
}
data = new char[len+1];
data[len] = \0;
}

Slide: 42 Matangini Chattopadhyay


Friends of More Than One class
class Matrix; // Forward declaration to make Vector prod(Matrix *pM, Vector *pV)
// declaration of crossprod legal {
class Vector { int V(pM->m);
public :
for (i = 0; i < pM->m; i++)
void Vector(int n) ;
for (j = 0; j < pM->n; j++)
friend Vector prod(Matrix *pM, Vector *pV);
int elements[10] ; {
int n; v[i] += pm->elements[i][j]*
}; pV->elements[i];
}
class Matrix {
}
public :
void Matrix(int m, int n) ;
friend Vector prod(Matrix *pM, Vector *pV);
private :
int elements[10][10];
int m, n;
};

Slide: 43 Matangini Chattopadhyay


Friend Members & Class
Member of a different class class Matrix;
class Vector {
may be a friend function.
public:

A class may be declared as a void Vector(int n);

friend implying all member Vector prod(Matrix *pM);

functions of that class are int elements[10];

friends. int n;
} ;
Friend-ship is neither class Matrix {

commutative nor transitive. public:


void Matrix(int m, int n);
Friends tend to break data friend Vector Vector::prod(Matrix *pM);
hiding. private:
int elements[10][10];
It is best to avoid friend in an int m, n;
ideal OO Design. } ;

Slide: 44 Matangini Chattopadhyay


Static Data
A static data member is class X {
shared by all the objects of a public:
class. static int count; // This is a declaration
X() { count++; }
Static data member may be }
public or private.
X::count = 0; //Definition & Initialization

Static data member must be int main()

initialized in a source file. {


X a, b, c;

It can be accessed printf(%d %d %d %d\n, X::count, a.count,


b.count, c.count);
with the class-name followed }
by the scope resolution
operator ::
The output will be 3 3 3 3
as a member of any object of
the class

Slide: 45 Matangini Chattopadhyay


Static Data: A List
void ListNode::print()
class ListNode
{
{
ListNode *x;
public:
x = ListNode::first;
static ListNode *first;
while (x != NULL)
private:
{
ListNode *next;
printf(%d , x->data);
int data;
x = x->next;
public:
}
ListNode(int x);
printf(\n);
print();
}
}
int main()
List Node *ListNode::first = NULL;
{
ListNode x(5);
ListNode::ListNode(int x)
ListNode x(7);
{
ListNode x(8);
data = x;
x.print();
next = NULL;
}
if (first == NULL)
first = this;
else The output will be 8 7 5
{
next = first;
first = this;
}
}

Slide: 46 Matangini Chattopadhyay


Static Member Functions

Static member functions


May be invoked
with the class-name::
class_name::static_function (args)
as part of any objects interface
any_object.static_function (args);

this pointer is not passed to a static function


must not refer to non-static members of its invoking
object
Philosophy of static members.

Slide: 47 Matangini Chattopadhyay


Static Members in Inline Functions
X.cxx
Not Safe #include X.hxx
void X::f()
X.hxx
{
Class X
X::g();
{ }
public:
The above code will not fail; The
static void f(); code in the following may fail
static String g(); however.
private: X1.cxx
static String s; #include X.hxx
} int main()

inline String X::g() {


X::g();
{
}
// do some operation on s
return s; Data members are guaranteed
} to be initialized before any non-
inline function is called.

Slide: 48 Matangini Chattopadhyay


Object Oriented Programming in C++
Operator Overloading

Slide: 49 Matangini Chattopadhyay


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.
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.

Slide: 50 Matangini Chattopadhyay


Example of overloading operator +
/ * string .h * / String operator+(char * text)
const int max_string_length = 128 ; {
class String { char *save = new char[len+1];
public : strcpy(save, data);
String opertator + (char *text) ; data = new char[len +strlen(text) + 1];
String opertator + (String &s1) ; strcpy(data, save);
String (char *data); stcat(data, text);
String () { data = NULL; len = 0; } delete[]save;
private : return (*this);
char *data; }
int len;
};

Slide: 51 Matangini Chattopadhyay


Overloading Assignment Operator
String & String: :operator=( char *rhs) String String: :operator=( String &rhs)
{ {
data = new char [strlen(rhs) + 1]; data = new char [rhs.len + 1];

strcpy ( data, rhs); strcpy ( data, rhs.data);

return *this ; return *this ;


}
}
Bug:
Bug: The following assignment
cannot be made
Memory Leak as previous data
String x(abc), y(def), z(ghi);
of this is not deleted. x = y = z;
(x.operator=((y).operator=(z)));

.
Solution
. Change the return type to
. String &

Slide: 52 Matangini Chattopadhyay


Overloading Assignment Operator

String & String: :operator (String &rhs)


{
delete [] data;
data = new char [rhs.len + 1];
strcpy ( data, rhs.data);
return *this ;
}

Bug:
Self Assignment will cause problem
Solution:
Check the following condition and return if false.
if (this != rhs) .

Slide: 53 Matangini Chattopadhyay


Reference & Overloading

Suppose that we have a class Integer & operator*(Integer &lhs, Integer &rhs)

Integer which has a private {

data member as int. The Integer *result = new Integer( lhs.data *


rhd.data);
following function is declared return *result;
as a friend of Integer. }
Integer & operator*(Integer &lhs, Integer &rhs)
{
Who deletes?
Integer result = lhs.data * rhd.data;
return result;
The caller.
} What about the following use?
Integer a(1), b(2), c(3), d(3);
Problem: Returning reference
Integer e =
to a local object. The code
wont work. a*b*c*d;

Slide: 54 Matangini Chattopadhyay


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
If the constructor uses new, assignment operator
may have to be overloaded.
If there is a need to define a copy constructor then
there must be a need to overload assignment
operator and vice-versa.

Slide: 55 Matangini Chattopadhyay


Overloading Unary Operators
Typically methods implementing unary
operators will not have any argument.
Exceptions:
post increment and post decrement operators.
As there are two operators with the same symbol +
+, the name of the function is the the same.
Prototype for pre increment function:
void operator ++ ( );

Prototype for post increment function:


void operator ++ (int a);

Slide: 56 Matangini Chattopadhyay


Operator Overloading Facts

Some operators can not be implemented as


global(friend) functions.
=, [] etc.

Some Operators cannot be overloaded


::,.*.?:,., sizeof() etc.

Precedence or arity of an operator cannot be


changed by overloading an operator.
Conditional Operators like &&, ||, comma
operator should not be overloaded.
Slide: 57 Matangini Chattopadhyay
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

In case of overloading stream operators, we


need friend due to the reason stated above.
Resolving in case of a conflict between friend
and method.
Slide: 58 Matangini Chattopadhyay
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;
}

Slide: 59 Matangini Chattopadhyay


Casting to User Defined Type
Constructors help
The following statement is not an error even when
an appropriate assignment operator is not defined
but an appropriate constructor is defined (which
constructor?)
String s1; s1 = example;
The assignment statement is converted to the
following
s1 = String(example);
Lots of temporary objects are created.
Even the following statement is correct:
s1 = s2 + abc + def;

Slide: 60 Matangini Chattopadhyay


Ambiguities: Example

Overuse of such casting f1 (const String & )


{
may lead to ambiguities }
as illustrated in the void
following example f1 (const example & )
{
/* ambig.cpp */ }
#include string.h int
class example { main ( )
public: {
example(const char *) { } ; // f1 (hello, world) ; is ambiguous
}; f1 ((String) hello world );
void f1 ((example) hello world );
// or provide void f1 (const char *)
return 0;
}

Slide: 61 Matangini Chattopadhyay


Ambiguity: Example
class B;
Which one to use for
class A {
public:
casting?
A (const B &); Constructor in A OR
...
}; Cast Operator in B

class B {
public:
operator A () const;
};
void f(const A &);

B b;
f(b); //Error - Ambiguous

Slide: 62 Matangini Chattopadhyay


Casting Pointers & References
Casting a value:
float f_var = 3.14;
cout << (int) f_var;
creates a temporary object
does not violate data encapsulation
Casting a pointer or reference
cout << *(( int *) &f_var);
cout << (int &) f_var;
Re-interprets representation of object
Violates data encapsulation

Slide: 63 Matangini Chattopadhyay