Download as pdf or txt
Download as pdf or txt
You are on page 1of 175

Module M11

L
Partha Pratim
Das
Programming in Modern C++

E
Weekly Recap

Objectives & Module M11: Classes and Objects

T
Outline

Classes

P
Objects

Data Members Partha Pratim Das

N
Complex
Rectangle
Stack Department of Computer Science and Engineering
Member Func. Indian Institute of Technology, Kharagpur
Complex
Rectangle ppd@cse.iitkgp.ac.in
Stack

this Pointer
All url’s in this module have been accessed in September, 2021 and found to be functional
State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.1
Weekly Recap

Module M11

• Revisited cv-qualifiers - const & volatile and compared macors with inline

L
Partha Pratim
Das
functions

E
Weekly Recap
• Introduced Reference variable or Alias in C++ and compared Call-by-reference with
Objectives &
Call-by-value & Return-by-reference with Return-by-value

T
Outline

Classes
• Studied the differences between References and Pointers

P
Objects

Data Members • Introduced Default parameter and Function overloading for Static Polymorphism

N
Complex
Rectangle
• Studied Overload Resolution with Default parameters and Function Overloading
Stack
• Understood the differences between Operators & Functions and introduced Operator
Member Func.
Complex Overloading with examples
Rectangle
Stack • Understood Operator Overloading Rules and Restrictions
this Pointer
• Did a roundup of Memory management in C and in C++
State
Complex • Introduced allocation (new) / de-allocation (delete) operators in C++, their
Rectangle
Stack
overloading and mixing with C styles
Module Summary
Programming in Modern C++ Partha Pratim Das M11.2
Module Objectives

Module M11

• Understand the concept of classes and objects in C++

L
Partha Pratim
Das

E
Weekly Recap

Objectives &

T
Outline

Classes

P
Objects

Data Members

N
Complex
Rectangle
Stack

Member Func.
Complex
Rectangle
Stack

this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.3
Module Outline

Module M11
1 Weekly Recap

L
Partha Pratim
Das 2 Classes

E
Weekly Recap 3 Objects
Objectives & 4 Data Members

T
Outline
Complex
Classes
Rectangle

P
Objects
Stack
Data Members

N
Complex
5 Member Functions
Rectangle Complex
Stack
Rectangle
Member Func. Stack
Complex
Rectangle 6 this Pointer
Stack
7 State of an Object
this Pointer
Complex
State
Rectangle
Complex
Rectangle
Stack
Stack
8 Module Summary
Module Summary
Programming in Modern C++ Partha Pratim Das M11.4
Classes

Module M11

L
Partha Pratim
Das

E
Weekly Recap

Objectives &

T
Outline

Classes

P
Objects

Data Members

N
Complex
Rectangle
Stack

Member Func.
Complex
Rectangle
Stack Classes
this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.5
Classes

Module M11

• A class is an implementation of a type. It is the only way to implement User-defined

L
Partha Pratim
Das
Data Type (UDT)

E
Weekly Recap • A class contains data members / attributes
Objectives &
• A class has operations / member functions / methods

T
Outline

Classes • A class defines a namespace

P
Objects • Thus, classes offer data abstraction / encapsulation of Object Oriented
Data Members Programming

N
Complex
Rectangle
• Classes are similar to structures that aggregate data logically
Stack
• A class is defined by class keyword
Member Func.
Complex
• Classes provide access specifiers for members to enforce data hiding that separates
Rectangle implementation from interface
Stack

this Pointer
◦ private — accessible inside the definition of the class
State ◦ public — accessible everywhere
Complex
Rectangle
• A class is a blue print for its instances (objects)
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.6
Objects

Module M11

L
Partha Pratim
Das

E
Weekly Recap

Objectives &

T
Outline

Classes

P
Objects

Data Members

N
Complex
Rectangle
Stack

Member Func.
Complex
Rectangle
Stack Objects
this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.7
Objects

Module M11

• An object of a class is an instance created according to its blue print. Objects can be

L
Partha Pratim
Das
automatically, statically, or dynamically created

E
Weekly Recap • A object comprises data members that specify its state
Objectives &
• A object supports member functions that specify its behavior

T
Outline

Classes • Data members of an object can be accessed by ”.” (dot) operator on the object

P
Objects • Member functions are invoked by ”.” (dot) operator on the object
Data Members • An implicit this pointer holds the address of an object. This serves the identity of the

N
Complex
Rectangle
object in C++
Stack
• this pointer is implicitly passed to methods
Member Func.
Complex
Rectangle
Stack

this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.8
Data Members

Module M11

L
Partha Pratim
Das

E
Weekly Recap

Objectives &

T
Outline

Classes

P
Objects

Data Members

N
Complex
Rectangle
Stack

Member Func.
Complex
Rectangle
Stack Data Members
this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.9
Program 11.01/02: Complex Numbers: Attributes

Module M11 C Program C++ Program

L
Partha Pratim // File Name:Complex_object.c // File Name:Complex_object_c++.cpp
Das
#include <stdio.h> #include <iostream>
using namespace std;

E
Weekly Recap

Objectives & typedef struct Complex { // struct class Complex { public: // class

T
Outline
double re, im; // Data members double re, im; // Data members
Classes } Complex; };

P
Objects
int main() { int main() {
// Variable c declared, initialized // Object c declared, initialized
Data Members Complex c = { 4.2, 5.3 }; Complex c = { 4.2, 5.3 };

N
Complex
printf("%lf %lf", c.re, c.im); // Use by dot cout << c.re << " " << c.im; // Use by dot
Rectangle
} }
Stack
----- -----
Member Func. 4.2 5.3 4.2 5.3
Complex
Rectangle
Stack • struct is a keyword in C for data aggregation • class is a new keyword in C+ for data aggregation
this Pointer • struct Complex is defined as composite data type con- • class Complex is defined as composite data type contain-
taining two double (re, im) data members ing two double (re, im) data members
State
• struct Complex is a derived data type used to create • class Complex is User-defined Data Type (UDT) used
Complex
Rectangle
Complex type variable c to create Complex type object c
Stack
• Data members are accessed using ’.’ operator • Data members are accessed using ’.’ operator.
• struct only aggregates • class aggregates and helps build a UDT
Module Summary
Programming in Modern C++ Partha Pratim Das M11.10
Program 11.03/04: Points and Rectangles: Attributes
C Program C++ Program
Module M11

// File Name:Rectangle_object.c // File Name:Rectangle_object_c++.cpp

L
Partha Pratim
Das #include <stdio.h> #include <iostream>
using namespace std;

E
Weekly Recap

Objectives & typedef struct { // struct Point class Point { public: // class Point

T
Outline int x; int y; int x; int y; // Data members
Classes
} Point; };
typedef struct { // Rect uses Point class Rect { public: // Rect uses Point

P
Objects Point TL; // Top-Left. Member of UDT Point TL; // Top-Left. Member of UDT
Data Members Point BR; // Bottom-Right. Member of UDT Point BR; // Bottom-Right. Member of UDT

N
Complex } Rect; };
Rectangle int main() { Rect r = { { 0, 2 }, { 5, 7 } }; int main() { Rect r = { { 0, 2 }, { 5, 7 } };
Stack // r.TL <-- { 0, 2 }; r.BR <-- { 5, 7 } // r.TL <-- { 0, 2 }; r.BR <-- { 5, 7 }
Member Func. // r.TL.x <-- 0; r.TL.y <-- 2 // r.TL.x <-- 0; r.TL.y <-- 2
Complex // Members of Structure r accessed // Rectangle Object r accessed
Rectangle printf("[(%d %d) (%d %d)]", cout << "[(" << r.TL.x << " " << r.TL.y <<
Stack r.TL.x, r.TL.y, r.BR.x, r.BR.y); ") (" << r.BR.x << " " << r.BR.y << ")]";
this Pointer } }
----- -----
State
[(0 2) (5 7)] [(0 2) (5 7)]
Complex
Rectangle
Stack
• Data members of user-defined data types
Module Summary
Programming in Modern C++ Partha Pratim Das M11.11
Program 11.05/06: Stacks: Attributes

Module M11
C Program C++ Program

L
Partha Pratim
Das // File Name:Stack_object.c // File Name:Stack_object_c++.cpp
#include <stdio.h> #include <iostream>

E
Weekly Recap using namespace std;
Objectives &

T
Outline typedef struct Stack { // struct Stack class Stack { public: // class Stack
Classes char data[100]; // Container for elements char data[100]; // Container for elements

P
int top; // Top of stack marker int top; // Top of stack marker
Objects
} Stack; };
Data Members

N
Complex // Codes for push(), pop(), top(), empty() // Codes for push(), pop(), top(), empty()
Rectangle
Stack int main() { int main() {
Member Func. // Variable s declared // Object s declared
Complex Stack s; Stack s;
Rectangle s.top = -1; s.top = -1;
Stack

this Pointer // Using stack for solving problems // Using stack for solving problems
} }
State
Complex
Rectangle
Stack
• Data members of mixed data types
Module Summary
Programming in Modern C++ Partha Pratim Das M11.12
Member Functions

Module M11

L
Partha Pratim
Das

E
Weekly Recap

Objectives &

T
Outline

Classes

P
Objects

Data Members

N
Complex
Rectangle
Stack

Member Func.
Complex
Rectangle
Stack Member Functions
this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.13
Program 11.07/08: Complex Numbers: Member Functions
C Program C++ Program
Module M11

// File Name:Complex_func.c // File Name:Complex_func_c++.cpp

L
Partha Pratim
Das #include <stdio.h> #include <iostream>
#include <math.h> #include <cmath>

E
Weekly Recap using namespace std;
Objectives & // Type as alias // Type as UDT

T
Outline typedef struct Complex { double re, im; } Complex; class Complex { public: double re, im;
Classes
// Norm of Complex Number - global fn. // Norm of Complex Number - method
double norm(Complex c) { // Parameter explicit double norm() { // Parameter implicit

P
Objects return sqrt(c.re*c.re + c.im*c.im); } return sqrt(re*re + im*im); }
Data Members // Print number with Norm - global fn. // Print number with Norm - method

N
Complex void print(Complex c) { // Parameter explicit void print() { // Parameter implicit
Rectangle printf("|%lf+j%lf| = ", c.re, c.im); cout << "|"<< re<< "+j"<< im<< "| = ";
Stack printf("%lf", norm(c)); // Call global cout << norm(); // Call method
Member Func. } }
Complex }; // End of class Complex
Rectangle int main() { Complex c = { 4.2, 5.3 }; int main() { Complex c = { 4.2, 5.3 };
Stack print(c); // Call global fn. with c as param c.print(); // Invoke method print of c
this Pointer } }
----- -----
State
|4.200000+j5.300000| = 6.762396 |4.2+j5.3| = 6.7624
Complex
Rectangle
Stack
• Access functions are global • Access functions are members
Module Summary
Programming in Modern C++ Partha Pratim Das M11.14
Program 11.09/10: Rectangles: Member Functions
Using struct Using class
Module M11
#include <iostream> #include <iostream>

L
Partha Pratim
Das #include <cmath> #include <cmath>
using namespace std; using namespace std;

E
Weekly Recap typedef struct { int x; int y; } Point; class Point { public: int x; int y; };
Objectives &
typedef struct { class Rect { public:

T
Outline Point TL; // Top-Left Point TL; // Top-Left
Classes
Point BR; // Bottom-Right Point BR; // Bottom-Right
} Rect;

P
Objects // Global function // Method
Data Members void computeArea(Rect r) { // Parameter explicit void computeArea() { // Parameter implicit

N
Complex cout << abs(r.TL.x - r.BR.x) * cout << abs(TL.x - BR.x) *
Rectangle abs(r.BR.y - r.TL.y); abs(BR.y - TL.y);
Stack } }
Member Func. };
Complex int main() { Rect r = { { 0, 2 }, { 5, 7 } }; int main() { Rect r = { { 0, 2 }, { 5, 7 } };
Rectangle
Stack computeArea(r); // Global fn. call r.computeArea(); // Method invocation
this Pointer
} }
----- -----
State 25 25
Complex
Rectangle
Stack • Access functions are global • Access functions are members
Module Summary
Programming in Modern C++ Partha Pratim Das M11.15
Program 11.11/12: Stacks: Member Functions
Using struct Using class
Module M11
#include <iostream> #include <iostream>

L
Partha Pratim
Das using namespace std; using namespace std;
typedef struct Stack { char data_[100]; int top_; class Stack { public:

E
Weekly Recap } Stack; char data_[100]; int top_;
Objectives &
// Global functions // Member functions

T
Outline bool empty(const Stack& s) { return (s.top_ == -1); } bool empty() { return (top_ == -1); }
Classes
char top(const Stack& s) { return s.data_[s.top_]; } char top() { return data_[top_]; }
void push(Stack& s, char x) { s.data_[++(s.top_)] = x; } void push(char x) { data_[++top_] = x; }

P
Objects void pop(Stack& s) { --(s.top_); } void pop() { --top_; }
Data Members };

N
Complex int main() { Stack s; s.top_ = -1; int main() { Stack s; s.top_ = -1;
Rectangle char str[10] = "ABCDE"; int i; char str[10] = "ABCDE"; int i;
Stack for (i = 0; i < 5; ++i) push(s, str[i]); for (i = 0; i < 5; ++i) s.push(str[i]);
Member Func. cout << "Reversed String: "; cout << "Reversed String: ";
Complex while (!empty(s)) { while (!s.empty()) {
Rectangle cout << top(s); pop(s); cout << s.top(); s.pop();
Stack } }
this Pointer
} }
----- -----
State Reversed String: EDCBA Reversed String: EDCBA
Complex
Rectangle
Stack
• Access functions are global • Access functions are members
Module Summary
Programming in Modern C++ Partha Pratim Das M11.16
this Pointer

Module M11

L
Partha Pratim
Das

E
Weekly Recap

Objectives &

T
Outline

Classes

P
Objects

Data Members

N
Complex
Rectangle
Stack

Member Func.
Complex
Rectangle
Stack this Pointer
this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.17
Program 11.13: this Pointer

Module M11 • An implicit this pointer holds the address of an object


• this pointer serves as the identity of the object in C++

L
Partha Pratim
Das
• Type of this pointer for a class X object: X * const this;

E
Weekly Recap this pointer is accessible only in member functions
Objectives & #include <iostream>

T
Outline
using namespace std;
Classes class X { public: int m1, m2;

P
Objects
void f(int k1, int k2) { // Sample member function
m1 = k1; // Implicit access without this pointer
Data Members this->m2 = k2; // Explicit access with this pointer

N
Complex
cout << "Id = " << this << endl; // Identity (address) of the object
Rectangle
}
Stack
};
Member Func. int main() { X a;
Complex a.f(2, 3);
Rectangle
cout << "Addr = " << &a << endl; // Address (identity) of the object
Stack
cout << "a.m1 = " << a.m1 << " a.m2 = " << a.m2 << endl;
this Pointer return 0;
State }
Complex
-----
Rectangle Id = 0024F918
Stack Addr = 0024F918
Module Summary
a.m1 = 2 a.m2 = 3
Programming in Modern C++ Partha Pratim Das M11.18
this Pointer

Module M11 • this pointer is implicitly passed to methods


In Source Code In Binary Code

L
Partha Pratim
Das
• class X { void f(int, int); ... } • void X::f(X * const this, int, int);

E
Weekly Recap • X a; a.f(2, 3); • X::f(&a, 2, 3); // &a = this
Objectives &

T
Outline
• Use of this pointer
Classes
◦ Distinguish member from non-member

P
Objects
class X { public: int m1, m2;
Data Members void f(int k1, int k2) {

N
Complex
m1 = k1; // this->m1 (member) is valid; this->k1 is invalid
Rectangle
this->m2 = k2; // m2 (member) is valid; this->k2 is invalid
Stack
}
Member Func. };
Complex
Rectangle
◦ Explicit Use
Stack // Link the object
class DoublyLinkedNode { public: DoublyLinkedNode *prev, *next; int data;
this Pointer
void append(DoublyLinkedNode *x) { next = x; x->prev = this; }
State }
Complex ---
Rectangle
// Return the object
Stack
Complex& inc() { ++re; ++im; return *this; }
Module Summary
Programming in Modern C++ Partha Pratim Das M11.19
State of an Object

Module M11

L
Partha Pratim
Das

E
Weekly Recap

Objectives &

T
Outline

Classes

P
Objects

Data Members

N
Complex
Rectangle
Stack

Member Func.
Complex
Rectangle
Stack State of an Object
this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.20
State of an Object: Complex

Module M11 • The state of an object is determined by the combined value of all its data members
class Complex { public:

L
Partha Pratim
Das double re_, im_; // ordered tuple of data members decide the state at any time

E
Weekly Recap double get_re { return re_; } // Read re_
Objectives &
void set_re(double re) { re_ = re; } // Write re_
double get_im { return im_; }

T
Outline // Read im_
void set_im(double im) { im_ = im; } // Write im_
Classes
};

P
Objects

Data Members Complex c = { 4.2, 5.3 };

N
Complex // STATE 1 of c = { 4.2, 5.3 } // Denotes a tuple / sequence
Rectangle • A method may change the state:
Stack
Complex c = { 4.2, 5.3 };
Member Func.
// STATE 1 of c = { 4.2, 5.3 }
Complex
Rectangle
Stack
c.set_re(6.4);
// STATE 2 of c = { 6.4, 5.3 }
this Pointer

State c.get_re();
Complex // STATE 2 of c = { 6.4, 5.3 } // No change of state
Rectangle
Stack c.set_im(7.8);
Module Summary // STATE 3 of c = { 6.4, 7.8 }
Programming in Modern C++ Partha Pratim Das M11.21
State of an Object: Rectangle

Module M11
// Data members of Rect class: Point TL; Point BR; // Point class type object

L
Partha Pratim
Das
// Data members of Point class: int x; int y;

Rectangle r = { { 0, 5 }, { 5, 0 } }; // Initialization

E
Weekly Recap
// STATE 1 of r = { { 0, 5 }, { 5, 0 } }
Objectives &
{ r.TL.x = 0; r.TL.y = 5; r.BR.x = 5; r.BR.y = 0 }

T
Outline

Classes r.TL.y = 9;

P
Objects // STATE 2 of r = { { 0, 9 }, { 5, 0 } }
Data Members

N
Complex
r.computeArea();
Rectangle
// STATE 2 of r = { { 0, 9 }, { 5, 0 } } // No change in state
Stack
Point p = { 3, 4 };
Member Func.
r.BR = p;
Complex
Rectangle
// STATE 3 of r = { { 0, 9 }, { 3, 4 } }
Stack

this Pointer

State
Complex
Rectangle
Stack

Module Summary
Programming in Modern C++ Partha Pratim Das M11.22
State of an Object: Stack

Module M11 // Data members of Stack class: char data[5] and int top;

L
Partha Pratim Stack s;
Das
// STATE 1 of s = {{?, ?, ?, ?, ?}, ?} // No data member is initialized

E
Weekly Recap
s.top_ = -1;
Objectives & // STATE 2 of s = {{?, ?, ?, ?, ?}, -1}

T
Outline

Classes s.push(’b’);

P
Objects // STATE 3 of s = {{’b’, ?, ?, ?, ?}, 0}
Data Members
s.push(’a’);

N
Complex
// STATE 4 of s = {{’b’, ’a’, ?, ?, ?}, 1}
Rectangle
Stack
s.empty();
Member Func. // STATE 4 of s = {{’b’, ’a’, ?, ?, ?}, 1} // No change of state
Complex
Rectangle
s.push(’t’);
Stack
// STATE 5 of s = {{’b’, ’a’, ’t’, ?, ?}, 2}
this Pointer

State s.top();
Complex // STATE 5 of s = {{’b’, ’a’, ’t’, ?, ?}, 2} // No change of state
Rectangle
Stack s.pops();
Module Summary
// STATE 6 of s = {{’b’, ’a’, ’t’, ?, ?}, 1}
Programming in Modern C++ Partha Pratim Das M11.23
Module Summary

Module M11
class Complex { public:
double re_, im_;

L
Partha Pratim
Das
• Class double norm() { // Norm of Complex Number

E
Weekly Recap return sqrt(re_ * re_ + im_ * im_);
Objectives & }

T
Outline };
Classes
• Attributes Complex::re_, Complex::im_

P
Objects

Data Members • Member Functions double Complex::norm();

N
Complex
Rectangle • Object Complex c = {2.6, 3.9};
Stack

Member Func.
c.re_ = 4.6;
Complex
• Access cout << c.im_;
Rectangle cout << c.norm();
Stack
• this Pointer double Complex::norm() { cout << this; return ... }
this Pointer

State Rectangle r = { { 0, 5 }, { 5, 0 } }; // STATE 1 r = { { 0, 5 }, { 5, 0 } }


Complex r.TL.y = 9; // STATE 2 r = { { 0, 9 }, { 5, 0 } }
• State of Object
Rectangle r.computeArea(); // STATE 2 r = { { 0, 9 }, { 5, 0 } }
Stack Point p = { 3, 4 }; r.BR = p; // STATE 3 r = { { 0, 9 }, { 3, 4 } }
Module Summary
Programming in Modern C++ Partha Pratim Das M11.24
Module M12

L
Partha Pratim
Das
Programming in Modern C++

E
Objectives &
Outlines
Module M12: Access Specifiers

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example Partha Pratim Das

N
Stack (public)
Risky
Stack (private) Department of Computer Science and Engineering
Safe Indian Institute of Technology, Kharagpur
Interface and
Implementation
ppd@cse.iitkgp.ac.in
Get-Set Idiom

Encapsulation
All url’s in this module have been accessed in September, 2021 and found to be functional
Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.1


Module Recap

Module M12
class Complex { public:
double re_, im_;

L
Partha Pratim
Das
• Class double norm() { // Norm of Complex Number

E
Objectives & return sqrt(re_ * re_ + im_ * im_);
Outlines
}

T
Access Specifiers };
Examples

• Attributes Complex::re_, Complex::im_

P
Information
Hiding

Stack Example
• Member Functions double Complex::norm();

N
Stack (public)
Risky
• Object Complex c = {2.6, 3.9};
Stack (private)
Safe
c.re_ = 4.6;
Interface and • Access cout << c.im_;
Implementation cout << c.norm();
Get-Set Idiom
• this Pointer double Complex::norm() { cout << this; return ... }
Encapsulation

Class as a Rectangle r = { { 0, 5 }, { 5, 0 } }; // STATE 1 r = { { 0, 5 }, { 5, 0 } }


Data-type r.TL.y = 9; // STATE 2 r = { { 0, 9 }, { 5, 0 } }
• State of Object
Module Summary r.computeArea(); // STATE 2 r = { { 0, 9 }, { 5, 0 } }
Point p = { 3, 4 }; r.BR = p; // STATE 3 r = { { 0, 9 }, { 3, 4 } }
Programming in Modern C++ Partha Pratim Das M12.2
Module Objectives

Module M12

• Understand access specifiers in C++ classes to control the visibility of members

L
Partha Pratim
Das
• Learn to design with Information Hiding

E
Objectives &
Outlines

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom

Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.3


Module Outline

Module M12
1 Access Specifiers

L
Partha Pratim
Das
Access Specifiers: Examples

E
Objectives &
Outlines 2 Information Hiding

T
Access Specifiers
Examples
3 Information Hiding: Stack Example
Stack (public)

P
Information
Hiding
Risky
Stack Example

N
Stack (public)
Stack (private)
Risky Safe
Stack (private)
Safe
Interface and Implementation
Interface and
Implementation 4 Get-Set Idiom
Get-Set Idiom

Encapsulation
5 Encapsulation
Class as a
Data-type 6 Class as a Data-type
Module Summary
7 Module Summary
Programming in Modern C++ Partha Pratim Das M12.4
Access Specifiers

Module M12

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom Access Specifiers


Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.5


Access Specifiers

Module M12

• Classes provide access specifiers for members (data as well as function) to enforce data

L
Partha Pratim
Das
hiding that separates implementation from interface

E
Objectives &
Outlines ◦ private — accessible inside the definition of the class
. member functions of the same class

T
Access Specifiers
Examples
◦ public — accessible everywhere

P
Information
Hiding . member functions of the same class
Stack Example . member function of a different class

N
Stack (public)
Risky . global functions
Stack (private)
Safe • The keywords public and private are the Access Specifiers
Interface and
Implementation • Unless specified, the access of the members of a class is considered private
Get-Set Idiom
• A class may have multiple access specifier. The effect of one continues till the next is
Encapsulation
encountered
Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.6


Program 12.01/02: Complex Number: Access Specification
Public data, Public method Private data, Public method
Module M12
#include <iostream> #include <iostream>

L
Partha Pratim
Das #include <cmath> #include <cmath>
using namespace std; using namespace std;

E
Objectives & class Complex { public: double re, im; class Complex { private: double re, im;
Outlines public: public:

T
Access Specifiers double norm() { return sqrt(re*re + im*im); } double norm() { return sqrt(re*re + im*im); }
Examples }; };
void print(const Complex& t) { // Global fn. void print(const Complex& t) { // Global fn.

P
Information
Hiding cout << t.re << "+j" << t.im << endl; cout << t.re << "+j" << t.im << endl;
// Complex::re / Complex::im: cannot access
Stack Example

N
Stack (public)
// private member declared in class ’Complex’
Risky
} }
Stack (private) int main() { Complex c = { 4.2, 5.3 }; // Okay int main() { Complex c = { 4.2, 5.3 }; // Error
Safe // ’initializing’: cannot convert from
Interface and // ’initializer-list’ to ’Complex’
Implementation
print(c); print(c);
Get-Set Idiom cout << c.norm(); cout << c.norm();
Encapsulation
} }
Class as a • public data can be accessed by any function • private data can be accessed only by methods
Data-type
• norm (method) can access (re, im) • norm (method) can access (re, im)
Module Summary • print (global) can access (re, im) • print (global) cannot access (re, im)
• main (global) can access (re, im) & initialize • main (global) cannot access (re, im) to initialize
Programming in Modern C++ Partha Pratim Das M12.7
Information Hiding

Module M12

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom Information Hiding


Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.8


Information Hiding

Module M12

• The private part of a class (attributes and member functions) forms its

L
Partha Pratim
Das
implementation because the class alone should be concerned with it and have the right

E
Objectives &
Outlines
to change it
• The public part of a class (attributes and member functions) constitutes its interface

T
Access Specifiers
Examples
which is available to all others for using the class

P
Information
Hiding
• Customarily, we put all attributes in private part and the member functions in public
Stack Example

N
Stack (public)
part. This ensures:
Risky
Stack (private)
◦ The state of an object can be changed only through one of its member functions
Safe (with the knowledge of the class)
Interface and
Implementation ◦ The behavior of an object is accessible to others through the member functions
Get-Set Idiom
• This is known as Information Hiding
Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.9


Information Hiding

Module M12

• For the sake of efficiency in design, we at times, put attributes in public and / or

L
Partha Pratim
Das
member functions in private. In such cases:

E
Objectives &
Outlines ◦ The public attributes should not decide the state of an object, and
◦ The private member functions cannot be part of the behavior of an object

T
Access Specifiers
Examples
We illustrate information hiding through two implementations of a stack

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom

Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.10


Information Hiding: Stack Example

Module M12

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom Information Hiding: Stack Example


Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.11


Program 12.03/04: Stack: Implementations using public data

Module M12 Using dynamic array Using vector

L
Partha Pratim #include <iostream> #include <iostream>
Das #include <cstdlib> #include <vector>
using namespace std; using namespace std;

E
Objectives &
Outlines
class Stack { public: char *data_; int top_; class Stack { public: vector<char> data_; int top_;
public: int empty() { return (top_ == -1); } public: int empty() { return (top_ == -1); }

T
Access Specifiers void push(char x) { data_[++top_] = x; } void push(char x) { data_[++top_] = x; }
Examples
void pop() { --top_; } void pop() { --top_; }

P
Information char top() { return data_[top_]; } char top() { return data_[top_]; }
Hiding }; };
Stack Example int main() { Stack s; char str[10] = "ABCDE"; int main() { Stack s; char str[10] = "ABCDE";

N
Stack (public) s.data_ = new char[100]; // Exposed Allocation s.data_.resize(100); // Exposed Sizing
Risky s.top_ = - 1; // Exposed Init s.top_ = -1; // Exposed Init
Stack (private)
Safe for(int i = 0; i < 5; ++i) s.push(str[i]); for(int i = 0; i < 5; ++i) s.push(str[i]);
Interface and
Implementation
// Outputs: EDCBA -- Reversed string // Outputs: EDCBA -- Reversed string
while(!s.empty()) { cout << s.top(); s.pop(); } while(!s.empty()) { cout << s.top(); s.pop(); }
Get-Set Idiom
delete [] s.data_; // Exposed De-Allocation
Encapsulation } }
Class as a
Data-type
• public data reveals the internals of the stack (no information hiding)
Module Summary • Spills data structure codes (Exposed Init / De-Init) into the application (main)
• To switch from array to vector or vice-versa the application needs to change
Programming in Modern C++ Partha Pratim Das M12.12
Program 12.03/04: Stack: Implementations using public data
Risky
Using dynamic array Using vector
Module M12
#include <iostream> #include <iostream>

L
Partha Pratim
Das #include <cstdlib> #include <vector>
using namespace std; using namespace std;

E
Objectives & class Stack { public: char *data_; int top_; class Stack { public: vector<char> data_; int top_;
Outlines public: int empty() { return (top_ == -1); } public: int empty() { return (top_ == -1); }

T
Access Specifiers void push(char x) { data_[++top_] = x; } void push(char x) { data_[++top_] = x; }
Examples void pop() { --top_; } void pop() { --top_; }
char top() { return data_[top_]; } char top() { return data_[top_]; }

P
Information
Hiding }; };
int main() { Stack s; char str[10] = "ABCDE"; int main() { Stack s; char str[10] = "ABCDE";
Stack Example

N
Stack (public)
s.data_ = new char[100]; // Exposed Allocation s.data_.resize(100); // Exposed Sizing
Risky
s.top_ = - 1; // Exposed Init s.top_ = -1; // Exposed Init
Stack (private)
Safe for(int i=0; i<5; ++i) s.push(str[i]); for(int i=0; i<5; ++i) s.push(str[i]);
Interface and s.top_ = 2; // STACK GETS INCONSISTENT s.top_ = 2; // STACK GETS INCONSISTENT
Implementation
// Outputs: CBA -- WRONG!!! // Outputs: CBA -- WRONG!!!
Get-Set Idiom while (!s.empty()) { cout << s.top(); s.pop(); } while (!s.empty()) { cout << s.top(); s.pop(); }
Encapsulation
delete [] s.data_; // Exposed De-Init
} }
Class as a
Data-type

Module Summary • Application may intentionally or inadvertently tamper the value of top – this corrupts the stack!
• s.top = 2; destroys consistency of the stack and causes wrong output
Programming in Modern C++ Partha Pratim Das M12.13
Program 12.05/06: Stack: Implementations using private data
Safe
Using dynamic array Using vector
Module M12
#include <iostream> #include <iostream>

L
Partha Pratim
Das #include <vector>
using namespace std; using namespace std;

E
Objectives & class Stack { private: char *data_; int top_; class Stack { private: vector<char> data_; int top_;
Outlines public: // Initialization and De-Initialization public: // Initialization and De-Initialization

T
Access Specifiers Stack(): data_(new char[100]), top_(-1) { } Stack(): top_(-1) { data_.resize(100); }
Examples ~Stack() { delete[] data_; } ~Stack() { };
// Stack LIFO Member Functions // Stack LIFO Member Functions

P
Information
Hiding int empty() { return (top_ == -1); } int empty() { return (top_ == -1); }
void push(char x) { data_[++top_] = x; } void push(char x) { data_[++top_] = x; }
Stack Example

N
Stack (public)
void pop() { --top_; } void pop() { --top_; }
Risky
char top() { return data_[top_]; } char top() { return data_[top_]; }
Stack (private) }; };
Safe int main() { Stack s; char str[10] = "ABCDE"; int main() { Stack s; char str[10] = "ABCDE";
Interface and for (int i=0; i<5; ++i) s.push(str[i]); for (int i=0; i<5; ++i) s.push(str[i]);
Implementation
while (!s.empty()) { cout << s.top(); s.pop(); } while (!s.empty()) { cout << s.top(); s.pop(); }
Get-Set Idiom } }
Encapsulation

Class as a • private data hides the internals of the stack (information hiding)
Data-type • Data structure codes contained within itself with initialization and de-initialization
Module Summary • To switch from array to vector or vice-versa the application needs no change
• Application cannot tamper stack – any direct access to top or data is compilation error!
Programming in Modern C++ Partha Pratim Das M12.14
Program 12.07: Interface and Implementation
Interface Implementation
Module M12

// File: Stack.h -- Interface // File: Stack.cpp -- Implementation

L
Partha Pratim
Das class Stack { private: // Implementation #include "Stack.h"
char *data_; int top_;

E
Objectives & public: // Interface Stack::Stack(): data_(new char[100]), top_(-1) { }
Outlines
Stack(); Stack::~Stack() { delete[] data_; }

T
Access Specifiers ~Stack(); int Stack::empty() { return (top_ == -1); }
Examples int empty(); void Stack::push(char x) { data_[++top_] = x; }
void push(char x); void Stack::pop() { --top_; }

P
Information
Hiding void pop(); char Stack::top() { return data_[top_]; }
Stack Example
char top();

N
Stack (public)
};
Risky
Stack (private)
Application
Safe
#include <iostream>
Interface and
using namespace std;
Implementation #include "Stack.h"
Get-Set Idiom int main() {
Stack s; char str[10] = "ABCDE";
Encapsulation
for (int i = 0; i < 5; ++i) s.push(str[i]);
Class as a while (!s.empty()) {
Data-type cout << s.top(); s.pop();
Module Summary }
}
Programming in Modern C++ Partha Pratim Das M12.15
Get-Set Idiom

Module M12

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom Get-Set Idiom


Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.16


Get–Set Methods: Idiom for fine-grained Access Control

Module M12 • We put attributes in private and the methods in public to restrict the access to data
• public methods to read (get) and / or write (set) data members provide fine-grained control

L
Partha Pratim
Das class MyClass { // private
int readWrite_; // Like re_, im_ in Complex -- common aggregated members

E
Objectives &
Outlines int readOnly_; // Like DateOfBirth, Emp_ID, RollNo -- should not need a change

T
Access Specifiers
Examples int writeOnly_; // Like Password -- reset if forgotten

P
Information
Hiding int invisible_; // Like top_, data_ in Stack -- keeps internal state
Stack Example

N
public:
Stack (public)
Risky
// get and set methods both to read as well as write readWrite_ member
Stack (private)
int getReadWrite() { return readWrite_; }
Safe void setReadWrite(int v) { readWrite_ = v; }
Interface and
Implementation // Only get method to read readOnly_ member - no way to write it
Get-Set Idiom int getReadOnly() { return readOnly_; }
Encapsulation
// Only set method to write writeOnly_ member - no way to read it
Class as a void setWriteOnly(int v) { writeOnly_ = v; }
Data-type

Module Summary // No method accessing invisible_ member directly - no way to read or write it
}
Programming in Modern C++ Partha Pratim Das M12.17
Get, Set Methods

Module M12

• Get, Set methods of a class are the interface defined for accessing and using the private

L
Partha Pratim
Das
data members. The implementation details of the data members are hidden.

E
Objectives &
Outlines • Not all data members are allowed to be updated or read, hence based on the
requirement of the interface, data members can be read only, write only, read and write

T
Access Specifiers
Examples
both or not visible at all.

P
Information
Hiding
• Let get and set be two variables of bool type which signifies presence of get and set
Stack Example

N
Stack (public)
methods respectively. In the below table, T denotes true (that is, method is present)
Risky and F denotes False (that is, method is absent)
Stack (private)
Safe
Interface and
Implementation Variables get set
Get-Set Idiom
Non Visible F F
Encapsulation
Read Only T F
Class as a
Data-type Write Only F T
Module Summary Read - Write T T
Programming in Modern C++ Partha Pratim Das M12.18
Program 12.08: Get - Set Methods: Employee Class
Get-Set Methods
Module M12

// File Name:Employee_c++.cpp:

L
Partha Pratim
Das #include <iostream>
#include <string>

E
Objectives & using namespace std;
Outlines

T
Access Specifiers class Employee { private:
Examples string name; // read and write: get_name() and set_name() defined
string address; // write only: set_addr() defined. No get method

P
Information
Hiding double sal_fixed; // read only: get_sal_fixed()defined. No set method
Stack Example
double sal_variable; // not visible: No get-set method

N
Stack (public)
Risky
public: Employee() { sal_fixed = 1200; sal_variable = 10; } // Initialize
Stack (private) string get_name() { return name; }
Safe void set_name(string name) { this->name = name; }
Interface and void set_addr(string address) { this->address = address; }
Implementation
double get_sal_fixed() { return sal_fixed; }
Get-Set Idiom // sal_variable (not visible) used in computation method salary()
Encapsulation double salary() { return sal_fixed + sal_variable; }
};
Class as a
Data-type
int main() {
Employee e1; e1.set_name("Ram"); e1.set_addr("Kolkata");
Module Summary cout << e1.get_name() << endl; cout << e1.get_sal_fixed() << endl << e1.salary() << endl;
}
Programming in Modern C++ Partha Pratim Das M12.19
Encapsulation

Module M12

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom Encapsulation


Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.20


Encapsulation

Module M12

• classes wrap data and functions acting on the data together as a single data structure. This is

L
Partha Pratim
Das
Aggregation

E
Objectives &
Outlines • The important feature introduced here is that members of a class has a access specifier,
which defines their visibility outside the class

T
Access Specifiers
Examples
• This helps in hiding information about the implementation details of data members and

P
Information
Hiding methods
Stack Example
◦ If properly designed, any change in the implementation, should not affect the interface

N
Stack (public)
Risky provided to the users
Stack (private)
Safe
◦ Also hiding the implementation details, prevents unwanted modifications to the data
Interface and members.
Implementation

Get-Set Idiom • This concept is known as Encapsulation which is provided by classes in C++.
Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.21


Class as a Data-type

Module M12

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Access Specifiers
Examples

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom Class as a Data-type


Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.22


Class as a Data-type

Module M12
• We can conclude now that class is a composite data type in C++ which has similar behaviour

L
Partha Pratim
Das to built in data types. We explain below with the Complex class (representing complex
number) as an example

E
Objectives &
Outlines

T
Access Specifiers // declare i to be of int type // declare c to be of Complex type
Examples int i; Complex c;

P
Information
Hiding // initialise i // initialise the real and imaginary components of c
Stack Example int i = 5; Complex c = { 4, 5 };

N
Stack (public)
Risky // print i // print the real and imaginary components of c
Stack (private) cout << i; cout << c.re << c.im;
Safe OR c.print(); // Method Complex::print() defined for printing
Interface and OR cout << c; // operator<<() overloaded for printing
Implementation

Get-Set Idiom // add two ints // add two Complex objects


Encapsulation int i = 5, j = 6; Complex c1 = { 4, 5 }, c2 = { 4, 6 };
i+j; c1.add(c2); // Method Complex::add() defined to add
Class as a
Data-type OR c1+c2; // operator+() overloaded to add
Module Summary

Programming in Modern C++ Partha Pratim Das M12.23


Module Summary

Module M12

• Access Specifiers help to control visibility of data members and methods of a class

L
Partha Pratim
Das
• The private access specifier can be used to hide information about the implementation

E
Objectives &
Outlines details of the data members and methods

T
Access Specifiers
Examples
• Get, Set methods are defined to provide an interface to use and access the data
members

P
Information
Hiding

Stack Example

N
Stack (public)
Risky
Stack (private)
Safe
Interface and
Implementation

Get-Set Idiom

Encapsulation

Class as a
Data-type

Module Summary

Programming in Modern C++ Partha Pratim Das M12.24


Module M13

L
Partha Pratim
Das
Programming in Modern C++

E
Objectives &
Outlines
Module M13: Constructors, Destructors & Object Lifetime

T
Constructor
Contrasting with
Member Functions

P
Parameterized
Default Parameters
Overloaded Partha Pratim Das

N
Destructor
Contrasting with
Member Functions Department of Computer Science and Engineering
Indian Institute of Technology, Kharagpur
Default
Constructor
ppd@cse.iitkgp.ac.in
Object Lifetime
Automatic
Static
Dynamic
All url’s in this module have been accessed in September, 2021 and found to be functional
Module Summary

Programming in Modern C++ Partha Pratim Das M13.1


Module Recap

Module M13

• Access Specifiers help to control visibility of data members and methods of a class

L
Partha Pratim
Das
• The private access specifier can be used to hide information about the implementation

E
Objectives &
Outlines details of the data members and methods

T
Constructor
Contrasting with
• Get, Set methods are defined to provide an interface to use and access the data
Member Functions
members

P
Parameterized
Default Parameters
Overloaded

N
Destructor
Contrasting with
Member Functions

Default
Constructor

Object Lifetime
Automatic
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.2


Module Objectives

Module M13

• Understand Object Construction (Initialization)

L
Partha Pratim
Das
• Understand Object Destruction (De-Initialization)

E
Objectives &
Outlines • Understand Object Lifetime

T
Constructor
Contrasting with
Member Functions

P
Parameterized
Default Parameters
Overloaded

N
Destructor
Contrasting with
Member Functions

Default
Constructor

Object Lifetime
Automatic
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.3


Module Outline

Module M13
1 Constructor

L
Partha Pratim
Das
Contrasting with Member Functions

E
Objectives &
Outlines
Parameterized
Default Parameters

T
Constructor
Contrasting with Overloaded
Member Functions

P
Parameterized
Default Parameters
2 Destructor
Overloaded
Contrasting with Member Functions

N
Destructor
Contrasting with
Member Functions
3 Default Constructor
Default
Constructor 4 Object Lifetime
Object Lifetime Automatic
Automatic
Static Static
Dynamic
Dynamic
Module Summary

5 Module Summary
Programming in Modern C++ Partha Pratim Das M13.4
Constructor

Module M13

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Constructor
Contrasting with
Member Functions

P
Parameterized
Default Parameters
Overloaded

N
Destructor
Contrasting with
Member Functions

Default
Constructor

Object Lifetime
Automatic
Constructor
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.5


Program 13.01/02: Stack: Initialization

Module M13 Public Data Private Data

L
Partha Pratim #include <iostream> #include <iostream>
Das using namespace std; using namespace std;
class Stack { public: // VULNERABLE DATA class Stack { private: // PROTECTED DATA

E
Objectives &
Outlines
char data_[10]; int top_; char data_[10]; int top_;
public: public:

T
Constructor void init() { top_ = -1; }
Contrasting with
Member Functions
int empty() { return (top_ == -1); } int empty() { return (top_ == -1); }

P
Parameterized void push(char x) { data_[++top_] = x; } void push(char x) { data_[++top_] = x; }
Default Parameters void pop() { --top_; } void pop() { --top_; }
Overloaded char top() { return data_[top_]; } char top() { return data_[top_]; }

N
Destructor
}; };
Contrasting with
int main() { char str[10] = "ABCDE"; int main() { char str[10] = "ABCDE";
Member Functions Stack s; s.top_ = -1; // Exposed initialization Stack s; s.init(); // Clean initialization
Default
Constructor for (int i = 0; i < 5; ++i) s.push(str[i]); for (int i = 0; i < 5; ++i) s.push(str[i]);
Object Lifetime
// s.top_ = 2; // RISK - CORRUPTS STACK // s.top_ = 2; // Compile error - SAFE
Automatic
while (!s.empty()) { cout << s.top(); s.pop(); } while (!s.empty()) { cout << s.top(); s.pop(); }
Static } }
Dynamic
• Spills data structure codes into application • No code in application, but init() to be called
Module Summary
• public data reveals the internals • private data protects the internals
• To switch container, application needs to change • Switching container is seamless
• Application may corrupt the stack! • Application cannot corrupt the stack
Programming in Modern C++ Partha Pratim Das M13.6
Program 13.02/03: Stack: Initialization

Module M13 Using init() Using Constructor

L
Partha Pratim #include <iostream> #include <iostream>
Das using namespace std; using namespace std;
class Stack { private: // PROTECTED DATA class Stack { private: // PROTECTED DATA

E
Objectives &
Outlines
char data_[10]; int top_; char data_[10]; int top_;
public: void init() { top_ = -1; } public: Stack() : top_(-1) { } // Initialization

T
Constructor int empty() { return (top_ == -1); } int empty() { return (top_ == -1); }
Contrasting with
Member Functions
void push(char x) { data_[++top_] = x; } void push(char x) { data_[++top_] = x; }

P
Parameterized void pop() { --top_; } void pop() { --top_; }
Default Parameters char top() { return data_[top_]; } char top() { return data_[top_]; }
Overloaded }; };

N
Destructor
int main() { char str[10] = "ABCDE"; int main() { char str[10] = "ABCDE";
Contrasting with
Stack s; s.init(); // Clean initialization Stack s; // Init by Stack::Stack() call
Member Functions

Default for (int i = 0; i < 5; ++i) s.push(str[i]); for (int i = 0; i < 5; ++i) s.push(str[i]);
Constructor // s.top_ = 2; // Compile error - SAFE
Object Lifetime
while(!s.empty()) { cout << s.top(); s.pop(); } while(!s.empty()) { cout << s.top(); s.pop(); }
Automatic
} }
Static
Dynamic
• init() serves no visible purpose – application may forget • Can initialization be made a part of instantiation?
Module Summary to call
• If application misses to call init(), we have a corrupt stack • Yes. Constructor is implicitly called at instantiation as set
by the compiler
Programming in Modern C++ Partha Pratim Das M13.7
Program 13.04/05: Stack: Constructor

Module M13 Automatic Array Dynamic Array

L
Partha Pratim #include <iostream> #include <iostream>
Das using namespace std; using namespace std;
class Stack { private: class Stack { private:

E
Objectives &
Outlines
char data_[10]; int top_; // Automatic char *data_; int top_; // Dynamic
public: Stack(); // Constructor public: Stack(); // Constructor

T
Constructor // More Stack methods // More Stack methods
Contrasting with
Member Functions
}; };

P
Parameterized Stack::Stack(): // Initialization List Stack::Stack(): data_(new char[10]), // Init List
Default Parameters top_(-1) { cout << "Stack::Stack()" << endl; top_(-1) { cout << "Stack::Stack()" << endl;
Overloaded } }

N
Destructor
int main() { char str[10] = "ABCDE"; int main() { char str[10] = "ABCDE";
Contrasting with
Stack s; // Init by Stack::Stack() call Stack s; // Init by Stack::Stack() call
Member Functions for (int i=0; i<5; ++i) s.push(str[i]); for (int i=0; i<5; ++i) s.push(str[i]);
Default while(!s.empty()) { cout << s.top(); s.pop(); } while(!s.empty()) { cout << s.top(); s.pop(); }
Constructor } }
Object Lifetime
----- -----
Automatic
Stack::Stack() Stack::Stack()
Static EDCBA EDCBA
Dynamic

Module Summary • top initialized to -1 in initialization list • top initialized to -1 in initialization list
• data [10] initialized by default (automatic) • data initialized to new char[10] in init list
• Stack::Stack() called automatically when control passes Stack s; – Guarantees initialization
Programming in Modern C++ Partha Pratim Das M13.8
Constructor: Contrasting with Member Functions

Module M13 Constructor Member Function

• •

L
Partha Pratim Is a static member function without this pointer – but gets Has implicit this pointer
Das
the pointer to the memory where the object is constructed
• Name is same as the name of the class • Any name different from name of class

E
Objectives &
Outlines class Stack { public: Stack(); }; class Stack { public: int empty(); };
• •

T
Constructor Has no return type - not even void Must have a return type - may be void
Contrasting with
Member Functions Stack::Stack(); // Not even void int Stack::empty();

P
Parameterized • Does not return anything. Has no return statement • Must have at least one return statement
Default Parameters
Stack::Stack(): top_(-1) int Stack::empty() { return (top_ == -1); }
Overloaded

N
{ } // Returns implicitly void pop()
Destructor { --top_; } // Implicit return for void
Contrasting with
Member Functions • Initializer list to initialize the data members • Not applicable
Default Stack::Stack(): // Initializer list
Constructor data_(new char[10]), // Init data_
Object Lifetime top_(-1) // Init top_
Automatic
{ }
Static • Implicit call by instantiation / operator new • Explicit call by the object
Dynamic
Stack s; // Calls Stack::Stack() s.empty(); // Calls Stack::empty(&s)
Module Summary
• May be public or private • May be public or private
• May have any number of parameters • May have any number of parameters
• Can be overloaded • Can be overloaded
Programming in Modern C++ Partha Pratim Das M13.9
Program 13.06: Complex: Parameterized Constructor

Module M13 #include <iostream>


#include <cmath>

L
Partha Pratim
Das
using namespace std;

class Complex { private: double re_, im_;

E
Objectives &
Outlines public:
Complex(double re, double im): // Constructor with parameters

T
Constructor
Contrasting with
re_(re), im_(im) // Initializer List: Parameters to initialize data members
Member Functions { }

P
Parameterized double norm() { return sqrt(re_*re_ + im_*im_); }
Default Parameters void print() {
Overloaded

N
cout << "|" << re_ << "+j" << im_ << "| = ";
Destructor cout << norm() << endl;
Contrasting with }
Member Functions
};
Default int main() { Complex c(4.2, 5.3), // Complex::Complex(4.2, 5.3)
Constructor d(1.6, 2.9); // Complex::Complex(1.6, 2.9)
Object Lifetime
Automatic c.print();
Static d.print();
Dynamic }
Module Summary -----
|4.2+j5.3| = 6.7624
|1.6+j2.9| = 3.3121
Programming in Modern C++ Partha Pratim Das M13.10
Program 13.07: Complex: Constructor with default parameters

Module M13 #include <iostream>


#include <cmath>

L
Partha Pratim
Das using namespace std;

E
Objectives & class Complex { private: double re_, im_; public:
Outlines
Complex(double re = 0.0, double im = 0.0) : // Constructor with default parameters

T
Constructor re_(re), im_(im) // Initializer List: Parameters to initialize data members
Contrasting with { }
Member Functions
double norm() { return sqrt(re_*re_ + im_*im_); }

P
Parameterized
void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Default Parameters
Overloaded
};

N
int main() {
Destructor Complex c1(4.2, 5.3), // Complex::Complex(4.2, 5.3) -- both parameters explicit
Contrasting with
Member Functions
c2(4.2), // Complex::Complex(4.2, 0.0) -- second parameter default
c3; // Complex::Complex(0.0, 0.0) -- both parameters default
Default
Constructor
c1.print();
Object Lifetime c2.print();
Automatic
c3.print();
Static
}
Dynamic
-----
Module Summary |4.2+j5.3| = 6.7624
|4.2+j0| = 4.2
|0+j0| = 0
Programming in Modern C++ Partha Pratim Das M13.11
Program 13.08: Stack: Constructor with default parameters

Module M13 #include <iostream>


#include <cstring>

L
Partha Pratim
Das
using namespace std;

class Stack { private: char *data_; int top_;

E
Objectives &
Outlines public: Stack(size_t = 10); // Size of data_ defaulted
~Stack() { delete data_[]; }

T
Constructor
Contrasting with
int empty() { return (top_ == -1); }
Member Functions void push(char x) { data_[++top_] = x; }

P
Parameterized void pop() { --top_; }
Default Parameters char top() { return data_[top_]; }
Overloaded
};

N
Destructor Stack::Stack(size_t s) : data_(new char[s]), top_(-1) // Array of size s allocated and set to data_
Contrasting with { cout << "Stack created with max size = " << s << endl; }
Member Functions

Default int main() { char str[] = "ABCDE"; int len = strlen(str);


Constructor Stack s(len); // Create a stack large enough for the problem
Object Lifetime
Automatic for (int i = 0; i < len; ++i) s.push(str[i]);
Static while (!s.empty()) { cout << s.top(); s.pop(); }
Dynamic }
Module Summary -----
Stack created with max size = 5
EDCBA
Programming in Modern C++ Partha Pratim Das M13.12
Program 13.09: Complex: Overloaded Constructors
#include <iostream>
Module M13
#include <cmath>
using namespace std;

L
Partha Pratim
Das
class Complex { private: double re_, im_; public:

E
Objectives &
Outlines
Complex(double re, double im): re_(re), im_(im) { } // Two parameters
Complex(double re): re_(re), im_(0.0) { } // One parameter

T
Constructor Complex(): re_(0.0), im_(0.0) { } // No parameter
Contrasting with
Member Functions

P
Parameterized
double norm() { return sqrt(re_*re_ + im_*im_); }
Default Parameters void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Overloaded };

N
Destructor
int main() {
Contrasting with
Complex c1(4.2, 5.3), // Complex::Complex(double, double)
Member Functions c2(4.2), // Complex::Complex(double)
Default c3; // Complex::Complex()
Constructor

Object Lifetime
c1.print();
Automatic
c2.print();
Static
c3.print();
Dynamic }
-----
Module Summary
|4.2+j5.3| = 6.7624
|4.2+j0| = 4.2
|0+j0| = 0
Programming in Modern C++ Partha Pratim Das M13.13
Program 13.10: Rect: Overloaded Constructors
#include <iostream>
Module M13
using namespace std;

L
Partha Pratim
Das class Pt { public: int x_, y_; Pt(int x, int y): x_(x), y_(y) { } }; // A Point
class Rect { Pt LT_, RB_; public:

E
Objectives &
Outlines
Rect(Pt lt, Pt rb):
LT_(lt), RB_(rb) { } // Cons 1: Points Left-Top lt and Right-Bottom rb

T
Constructor Rect(Pt lt, int h, int w):
Contrasting with
Member Functions
LT_(lt), RB_(Pt(lt.x_+w, lt.y_+h)) { } // Cons 2: Point Left-Top lt, height h & width w

P
Parameterized
Rect(int h, int w):
Default Parameters LT_(Pt(0, 0)), RB_(Pt(w, h)) { } // Cons 3: height h, width w & Point origin as Left-Top
Overloaded int area() { return (RB_.x_-LT_.x_) * (RB_.y_-LT_.y_); }

N
Destructor
};
Contrasting with
int main() { Pt p1(2, 5), p2(8, 10);
Member Functions Rect r1(p1, p2), // Cons 1: Rect::Rect(Pt, Pt)
Default r2(p1, 5, 6), // Cons 2: Rect::Rect(Pt, int, int)
Constructor r3(5, 6); // Cons 3: Rect::Rect(int, int)
Object Lifetime
cout << "Area of r1 = " << r1.area() << endl;
Automatic
cout << "Area of r2 = " << r2.area() << endl;
Static
cout << "Area of r3 = " << r3.area() << endl;
Dynamic }
-----
Module Summary
Area of r1 = 30
Area of r2 = 30
Area of r3 = 30
Programming in Modern C++ Partha Pratim Das M13.14
Destructor

Module M13

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Constructor
Contrasting with
Member Functions

P
Parameterized
Default Parameters
Overloaded

N
Destructor
Contrasting with
Member Functions

Default
Constructor

Object Lifetime
Automatic
Destructor
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.15


Program 13.11/12: Stack: Destructor

Module M13 Resource Release by User Automatic Resource Release

L
Partha Pratim #include <iostream> #include <iostream>
Das using namespace std; using namespace std;
class Stack { char *data_; int top_; // Dynamic class Stack { char *data_; int top_; // Dynamic

E
Objectives &
Outlines
public: Stack(): data_(new char[10]), top_(-1) public: Stack(): data_(new char[10]), top_(-1)
{ cout << "Stack() called\n"; } // Constructor { cout << "Stack() called\n"; } // Constructor

T
Constructor void de_init() { delete [] data_; } ~Stack() { cout << "\n~Stack() called\n";
Contrasting with
Member Functions
delete [] data_; // Destructor

P
Parameterized }
Default Parameters // More Stack methods // More Stack methods
Overloaded }; };

N
Destructor
int main() { char str[10] = "ABCDE"; int main() { char str[10] = "ABCDE";
Contrasting with
Stack s; // Init by Stack::Stack() call Stack s; // Init by Stack::Stack() call
Member Functions // Reverse string using Stack // Reverse string using Stack
Default s.de_init();
Constructor } } // De-Init by automatic Stack::~Stack() call
Object Lifetime
----- -----
Automatic
Stack() called Stack() called
Static EDCBA EDCBA
Dynamic ~Stack() called
Module Summary

• data leaks unless released within the scope of s • Can de-initialization be a part of scope rules?
• When to call de init()? User may forget to call • Yes. Destructor is implicitly called at end of scope
Programming in Modern C++ Partha Pratim Das M13.16
Destructor: Contrasting with Member Functions

Module M13 Destructor Member Function

• •

L
Partha Pratim Has implicit this pointer Has implicit this pointer
Das
• Name is ˜ followed by the name of the class • Any name different from name of class

E
Objectives & class Stack { public: class Stack { public:
Outlines
~Stack(); int empty();

T
Constructor }; };
Contrasting with
Member Functions • Has no return type - not even void • Must have a return type - may be void

P
Parameterized Stack::~Stack(); // Not even void int Stack::empty();
Default Parameters
Overloaded
• Does not return anything. Has no return statement • Must have at least one return statement

N
Destructor
Stack::~Stack() int Stack::empty()
Contrasting with
{ } // Returns implicitly { return (top_ == -1); }
Member Functions
• Implicitly called at end of scope or by operator delete. • Explicit call by the object
Default May be called explicitly by the object (rare)
Constructor
{
Object Lifetime Stack s; s.empty(); // Calls Stack::empty(&s)
Automatic // ...
Static
} // Calls Stack::~Stack(&s) implicitly
Dynamic

Module Summary
• May be public or private • May be public or private
• No parameter is allowed - unique for the class • May have any number of parameters
• Cannot be overloaded • Can be overloaded
Programming in Modern C++ Partha Pratim Das M13.17
Default Constructor

Module M13

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Constructor
Contrasting with
Member Functions

P
Parameterized
Default Parameters
Overloaded

N
Destructor
Contrasting with
Member Functions

Default
Constructor

Object Lifetime
Automatic
Default Constructor
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.18


Default Constructor / Destructor

Module M13
• Constructor

L
Partha Pratim
Das ◦ A constructor with no parameter is called a Default Constructor
◦ If no constructor is provided by the user, the compiler supplies a free default

E
Objectives &
Outlines
constructor

T
Constructor
Contrasting with ◦ Compiler-provided (free default) constructor, understandably, cannot initialize the
Member Functions
object to proper values. It has no code in its body

P
Parameterized
Default Parameters
◦ Default constructors (free or user-provided) are required to define arrays of objects
Overloaded

N
Destructor • Destructor
Contrasting with
Member Functions ◦ If no destructor is provided by the user, the compiler supplies a free default
Default
Constructor
destructor
Object Lifetime
◦ Compiler-provided (free default) destructor has no code in its body
Automatic
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.19


Program 13.13: Complex: Default Constructor: User Defined
#include <iostream>
Module M13
#include <cmath>
using namespace std;

L
Partha Pratim
Das
class Complex { private: double re_, im_; public:

E
Objectives &
Outlines
Complex(): re_(0.0), im_(0.0) // Default Constructor having no parameter
{ cout << "Ctor: (" << re_ << ", " << im_ << ")" << endl; }

T
Constructor ~Complex() { cout << "Dtor: (" << re_ << ", " << im_ << ")" << endl; } // Destructor
Contrasting with
Member Functions
double norm() { return sqrt(re_*re_ + im_*im_); }

P
Parameterized
void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Default Parameters void set(double re, double im) { re_ = re; im_ = im; }
Overloaded };

N
Destructor
int main() { Complex c; // Default constructor -- user provided
Contrasting with
c.print(); // Print initial values
Member Functions c.set(4.2, 5.3); // Set components
Default
c.print(); // Print values set
Constructor } // Destuctor
Object Lifetime
-----
Automatic
Ctor: (0, 0)
Static
|0+j0| = 0
Dynamic |4.2+j5.3| = 6.7624
Dtor: (4.2, 5.3)
Module Summary

• User has provided a default constructor


Programming in Modern C++ Partha Pratim Das M13.20
Program 13.14: Complex: Default Constructor: Free
#include <iostream>
Module M13
#include <cmath>
using namespace std;

L
Partha Pratim
Das
class Complex { private: double re_, im_; // private data

E
Objectives &
Outlines
public: // No constructor given be user. So compiler provides a free default one
double norm() { return sqrt(re_*re_ + im_*im_); }

T
Constructor void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Contrasting with
Member Functions
void set(double re, double im) { re_ = re; im_ = im; }

P
Parameterized
};
Default Parameters int main() { Complex c; // Free constructor from compiler. Initialization with garbage
Overloaded

N
Destructor
c.print(); // Print initial value - garbage
Contrasting with
c.set(4.2, 5.3); // Set proper components
Member Functions c.print(); // Print values set
Default
} // Free destuctor from compiler
Constructor -----
Object Lifetime
|-9.25596e+061+j-9.25596e+061| = 1.30899e+062
Automatic
|4.2+j5.3| = 6.7624
Static
Dynamic
• User has provided no constructor / destructor
Module Summary • Compiler provides default (free) constructor / destructor
• Compiler-provided constructor does nothing – components have garbage values
• Compiler-provided destructor does nothing
Programming in Modern C++ Partha Pratim Das M13.21
Object Lifetime

Module M13

L
Partha Pratim
Das

E
Objectives &
Outlines

T
Constructor
Contrasting with
Member Functions

P
Parameterized
Default Parameters
Overloaded

N
Destructor
Contrasting with
Member Functions

Default
Constructor

Object Lifetime
Automatic
Object Lifetime
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.22


Object Lifetime

Module M13
• In OOP, the object lifetime (or life cycle) of an object is the time between an object’s
creation and its destruction

L
Partha Pratim
Das
• Rules for object lifetime vary significantly:

E
Objectives &
Outlines ◦ Between languages
◦ in some cases between implementations of a given language, and

T
Constructor
Contrasting with
Member Functions ◦ lifetime of a particular object may vary from one run of the program to another

P
Parameterized
Default Parameters • Context C++: Object Llifetime coincides with Variable Lifetime (the extent of a
Overloaded
variable when in a program’s execution the variable has a meaningful value) of a

N
Destructor
Contrasting with
variable with that object as value (both for static variables and automatic variables).
Member Functions
However, in general, object lifetime may not be tied to the lifetime of any one variable
Default
Constructor • Context Java / Python: In OO languages that use garbage collection (GC), objects
Object Lifetime are allocated on the heap
Automatic
Static ◦ object lifetime is not determined by the lifetime of a given variable
Dynamic
◦ the value of a variable holding an object actually corresponds to a reference to the object,
Module Summary
not the object itself, and
◦ destruction of the variable just destroys the reference, not the underlying object
Programming in Modern C++ Partha Pratim Das M13.23
Object Lifetime: When is an Object ready?
How long can it be used?
Application Class Code
Module M13

void MyFunc() { // E1: Allocation of c on Stack

L
Partha Pratim Complex::Complex(double re = 0.0, // Constructor
Das ... double im = 0.0):
Complex c; // E2: Constructor called re_(re), im_(im) // E3: Initialization

E
Objectives &
Outlines
... { // E4: Object Lifetime STARTS with initialization
cout << "Ctor:" << endl;

T
Constructor c.norm(); // E5: Use }
Contrasting with
Member Functions
... double Complex::norm() // E6 norm executes

P
Parameterized { return sqrt(re_*re_ + im_*im_); }
Default Parameters return; // E7: Destructor called Complex::~Complex() { cout << "Dtor:" << endl;
Overloaded } // E9: De-Allocation of c from Stack } // E8: Object Lifetime ENDS with destructor

N
Destructor
Contrasting with
Member Functions Event Sequence and Object Lifetime
Default E1 MyFunc called. Stackframe allocated. c is a part of Stackframe
Constructor E2 Control to pass to Complex c. Ctor Complex::Complex(&c) called with the address of c on the frame
Object Lifetime E3 Control on Initializer list of Complex::Complex(). Data members initialized (constructed)
Automatic E4 Object Lifetime STARTS for c. Control reaches the start of the body of Constructor. Constructor executes
Static E5 Control at c.norm(). Complex::norm(&c) called. Object is being used
Dynamic E6 Complex::norm() executes
Module Summary E7 Control to pass return in MyFunc. Desturctor Complex::~Complex(&c) called
E8 Destructor executes. Control reaches the end of the body of Destructor. Object Lifetime ENDS for c
E9 return executes. Stackframe including c de-allocated. Control returns to caller
Programming in Modern C++ Partha Pratim Das M13.24
Object Lifetime

Module M13
• Execution Stages

L
Partha Pratim
Das ◦ Memory Allocation and Binding
◦ Constructor Call and Execution

E
Objectives &
Outlines ◦ Object Use
◦ Destructor Call and Execution

T
Constructor
Contrasting with
Member Functions
◦ Memory De-Allocation and De-Binding

P
Parameterized
Default Parameters
• Object Lifetime
Overloaded ◦ Starts with execution of Constructor Body

N
Destructor
Contrasting with
. Must follow Memory Allocation
Member Functions . As soon as Initialization ends and control enters Constructor Body
Default
Constructor ◦ Ends with execution of Destructor Body
Object Lifetime . As soon as control leaves Destructor Body
Automatic
Static
. Must precede Memory De-allocation
Dynamic
◦ For Objects of Built-in / Pre-Defined Types
Module Summary
. No Explicit Constructor / Destructor
. Lifetime spans from object definition to end of scope
Programming in Modern C++ Partha Pratim Das M13.25
Program 13.15: Complex: Object Lifetime: Automatic

Module M13 #include <iostream>


#include <cmath>

L
Partha Pratim
Das
using namespace std;
class Complex { private: double re_, im_; public:
Complex(double re = 0.0, double im = 0.0): re_(re), im_(im) // Ctor

E
Objectives &
Outlines { cout << "Ctor: (" << re_ << ", " << im_ << ")" << endl; }
~Complex() { cout << "Dtor: (" << re_ << ", " << im_ << ")" << endl; } // Dtor

T
Constructor
Contrasting with
Member Functions double norm() { return sqrt(re_*re_ + im_*im_); }

P
Parameterized void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Default Parameters };
Overloaded
int main() {

N
Destructor Complex c(4.2, 5.3), d(2.4); // Complex::Complex() called -- c, then d -- objects ready
Contrasting with c.print(); // Using objects
Member Functions
d.print();
Default } // Scope over, objects no more available. Complex::~Complex() called -- d then c in the reverse order!
Constructor

Object Lifetime -----


Automatic
Ctor: (4.2, 5.3)
Static
Ctor: (2.4, 0)
Dynamic
|4.2+j5.3| = 6.7624
Module Summary |2.4+j0| = 2.4
Dtor: (2.4, 0)
Dtor: (4.2, 5.3)
Programming in Modern C++ Partha Pratim Das M13.26
Program 13.16: Complex: Object Lifetime:
Automatic: Array of Objects
Module M13 #include <iostream>
#include <cmath>

L
Partha Pratim using namespace std;
Das
class Complex { private: double re_, im_; public:
Complex(double re = 0.0, double im = 0.0) : re_(re), im_(im) // Ctor

E
Objectives &
Outlines { cout << "Ctor: (" << re_ << ", " << im_ << ")" << endl; }
~Complex() { cout << "Dtor: (" << re_ << ", " << im_ << ")" << endl; } // Dtor

T
Constructor
void opComplex(double i) { re_ += i; im_ += i; } // Some operation with Complex
Contrasting with
Member Functions double norm() { return sqrt(re_*re_ + im_*im_); }

P
Parameterized void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Default Parameters };
Overloaded int main() { Complex c[3]; // Default ctor Complex::Complex() called thrice -- c[0], c[1], c[2]

N
Destructor for (int i = 0; i < 3; ++i) { c[i].opComplex(i); c[i].print(); } // Use array
Contrasting with } // Scope over. Complex::~Complex() called thrice -- c[2], c[1], c[0] in the reverse order
Member Functions

Default -----
Constructor Ctor: (0, 0)
Object Lifetime
Ctor: (0, 0)
Automatic
Ctor: (0, 0)
Static |0+j0| = 0
Dynamic |1+j1| = 1.41421
|2+j2| = 2.82843
Module Summary
Dtor: (2, 2)
Dtor: (1, 1)
Dtor: (0, 0)
Programming in Modern C++ Partha Pratim Das M13.27
Program 13.17: Complex: Object Lifetime: Static

Module M13
#include <iostream>
#include <cmath>
using namespace std;

L
Partha Pratim
Das
class Complex { private: double re_, im_; public:

E
Objectives &
Outlines
Complex(double re = 0.0, double im = 0.0): re_(re), im_(im) // Ctor
{ cout << "Ctor: (" << re_ << ", " << im_ << ")" << endl; }

T
Constructor ~Complex() { cout << "Dtor: (" << re_ << ", " << im_ << ")" << endl; } // Dtor
Contrasting with
Member Functions

P
Parameterized double norm() { return sqrt(re_*re_ + im_*im_); }
Default Parameters void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Overloaded };

N
Destructor
Complex c(4.2, 5.3); // Static (global) object c
Contrasting with
// Constructed before main starts. Destructed after main ends
Member Functions int main() {
Default cout << "main() Starts" << endl; ----- OUTPUT -----
Constructor Complex d(2.4); // Ctor for d Ctor: (4.2, 5.3)
Object Lifetime
main() Starts
Automatic
c.print(); // Use static object Ctor: (2.4, 0)
Static
d.print(); // Use local object |4.2+j5.3| = 6.7624
Dynamic } // Dtor for d |2.4+j0| = 2.4
Dtor: (2.4, 0)
Module Summary
// Dtor for c Dtor: (4.2, 5.3)

Programming in Modern C++ Partha Pratim Das M13.28


Program 13.18: Complex: Object Lifetime: Dynamic
#include <iostream>
Module M13
#include <cmath>
using namespace std;

L
Partha Pratim
Das class Complex { private: double re_, im_; public:
Complex(double re = 0.0, double im = 0.0): re_(re), im_(im) // Ctor

E
Objectives &
Outlines
{ cout << "Ctor: (" << re_ << ", " << im_ << ")" << endl; }
~Complex() { cout << "Dtor: (" << re_ << ", " << im_ << ")" << endl; } // Dtor

T
Constructor double norm() { return sqrt(re_*re_ + im_*im_); }
Contrasting with
Member Functions
void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }

P
Parameterized
};
Default Parameters int main() { unsigned char buf[100]; // Buffer for placement of objects
Overloaded Complex* pc = new Complex(4.2, 5.3); // new: allocates memory, calls Ctor

N
Destructor
Complex* pd = new Complex[2]; // new []: allocates memory ----- OUTPUT -----
Contrasting with
// calls default Ctor twice Ctor: (4.2, 5.3)
Member Functions Complex* pe = new (buf) Complex(2.6, 3.9); // placement new: only calls Ctor Ctor: (0, 0)
Default
// No alloc. of memory, uses buf Ctor: (0, 0)
Constructor // Use objects Ctor: (2.6, 3.9)
Object Lifetime
pc->print(); |4.2+j5.3| = 6.7624
Automatic
pd[0].print(); pd[1].print(); |0+j0| = 0
Static
pe->print(); |0+j0| = 0
Dynamic // Release of objects - can be done in any order |2.6+j3.9| = 4.68722
delete pc; // delete: calls Dtor, release memory Dtor: (4.2, 5.3)
Module Summary
delete [] pd; // delete[]: calls 2 Dtor’s, release memory Dtor: (0, 0)
pe->~Complex(); // No delete: explicit call to Dtor. Use with extreme care Dtor: (0, 0)
} Dtor: (2.6, 3.9)
Programming in Modern C++ Partha Pratim Das M13.29
Module Summary

Module M13

• Objects are initialized by Constructors that can be Parameterized and / or Overloaded

L
Partha Pratim
Das
• Default Constructor does not take any parameter – necessary for arrays of objects

E
Objectives &
Outlines • Objects are cleaned-up by Destructors. Destructor for a class is unique

T
Constructor
Contrasting with • Compiler provides free Default Constructor and Destructor, if not provides by the
Member Functions
program

P
Parameterized
Default Parameters
Overloaded • Objects have a well-defined lifetime spanning from execution of the beginning of the

N
Destructor body of a constructor to the execution till the end of the body of the destructor
Contrasting with
Member Functions
• Memory for an object must be available before its construction and can be released
Default
Constructor only after its destruction
Object Lifetime
Automatic
Static
Dynamic

Module Summary

Programming in Modern C++ Partha Pratim Das M13.30


Module M14

L
Partha Pratim
Das
Programming in Modern C++

E
Obj. & Outlines

Obj. Lifetime Module M14: Copy Constructor and Copy Assignment Operator

T
String
Date

P
Rect
Name & Address
CreditCard
Partha Pratim Das

N
Copy Constructor
Call by Value
Signature Department of Computer Science and Engineering
Data Members Indian Institute of Technology, Kharagpur
Free Copy & Pitfall

Assignment Op. ppd@cse.iitkgp.ac.in


Copy Objects
Self-Copy
Signature All url’s in this module have been accessed in September, 2021 and found to be functional
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.1


Module Recap

Module M14

• Objects are initialized by Constructors that can be Parameterized and / or Overloaded

L
Partha Pratim
Das
• Default Constructor does not take any parameter – necessary for arrays of objects

E
Obj. & Outlines

Obj. Lifetime
• Objects are cleaned-up by Destructors. Destructor for a class is unique

T
String
Date
• Compiler provides free Default Constructor and Destructor, if not provides by the
program

P
Rect
Name & Address
CreditCard
• Objects have a well-defined lifetime spanning from execution of the beginning of the

N
Copy Constructor
Call by Value
body of a constructor to the execution till the end of the body of the destructor
Signature
Data Members
• Memory for an object must be available before its construction and can be released
Free Copy & Pitfall only after its destruction
Assignment Op.
Copy Objects
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.2


Module Objectives

Module M14

• More on Object Lifetime

L
Partha Pratim
Das
• Understand Copy Construction

E
Obj. & Outlines

Obj. Lifetime
• Understand Copy Assignment Operator

T
String
Date
• Understand Shallow and Deep Copy

P
Rect
Name & Address
CreditCard

N
Copy Constructor
Call by Value
Signature
Data Members
Free Copy & Pitfall

Assignment Op.
Copy Objects
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.3


Module Outline

Module M14 1 Object Lifetime Examples


String

L
Partha Pratim
Das Date: Practice
Rect: Practice

E
Obj. & Outlines
Name & Address: Practice
Obj. Lifetime
CreditCard: Practice

T
String
Date 2 Copy Constructor

P
Rect
Call by Value
Name & Address
CreditCard
Signature

N
Copy Constructor
Data Members
Call by Value Free Copy Constructor and Pitfalls
Signature
3 Copy Assignment Operator
Data Members
Free Copy & Pitfall Copy Objects
Assignment Op. Self-Copy
Copy Objects Signature
Self-Copy Free Assignment Operator
Signature
Free Assignment 4 Comparison of Copy Constructor and Copy Assignment Operator
Comparison 5 Class as a Data-type
Class as Type
6 Module Summary
Module Summary Programming in Modern C++ Partha Pratim Das M14.4
Object Lifetime Examples

Module M14

L
Partha Pratim
Das

E
Obj. & Outlines

Obj. Lifetime

T
String
Date

P
Rect
Name & Address
CreditCard

N
Copy Constructor
Call by Value
Signature
Data Members
Free Copy & Pitfall

Assignment Op.
Copy Objects
Object Lifetime Examples
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.5


Program 14.01/02: Order of Initialization: Order of Data Members
#include <iostream> #include <iostream>
Module M14 using namespace std; using namespace std;
int init_m1(int m) { // Func. to init m1_ int init_m1(int m) { // Func. to init m1_

L
Partha Pratim
Das cout << "Init m1_: " << m << endl; cout << "Init m1_: " << m << endl;
return m; return m;

E
Obj. & Outlines } }
Obj. Lifetime
int init_m2(int m) { // Func. to init m2_ int init_m2(int m) { // Func. to init m2_

T
String
cout << "Init m2_: " << m << endl; cout << "Init m2_: " << m << endl;
Date return m; return m;
} }

P
Rect
Name & Address class X { int m1_; // Initialize 1st class X { int m2_; // Order of data members swapped
CreditCard int m2_; // Initialize 2nd int m1_;

N
Copy Constructor public: X(int m1, int m2) : public: X(int m1, int m2) :
Call by Value
m1_(init_m1(m1)), // Called 1st m1_(init_m1(m1)), // Called 2nd
Signature m2_(init_m2(m2)) // Called 2nd m2_(init_m2(m2)) // Called 1st
Data Members { cout << "Ctor: " << endl; } { cout << "Ctor: " << endl; }
Free Copy & Pitfall ~X() { cout << "Dtor: " << endl; } }; ~X() { cout << "Dtor: " << endl; } };
Assignment Op.
int main() { X a(2, 3); return 0; } int main() { X a(2, 3); return 0; }
Copy Objects
----- -----
Self-Copy Init m1_: 2 Init m2_: 3
Signature Init m2_: 3 Init m1_: 2
Free Assignment Ctor: Ctor:
Comparison
Dtor: Dtor:
Class as Type • Order of initialization does not depend on the order in the initialization list. It depends on the order of data members
Module Summary
in the definition
Programming in Modern C++ Partha Pratim Das M14.6
Program 14.03/04: A Simple String Class
C Style C++ Style
Module M14
#include <iostream> #include <iostream>

L
Partha Pratim #include <cstring> #include <cstring>
Das
#include <cstdlib> #include <cstdlib>
using namespace std; using namespace std;

E
Obj. & Outlines
struct String { char *str_; // Container class String { char *str_; // Container
Obj. Lifetime size_t len_; // Length size_t len_; // Length

T
String }; public: String(char *s) : str_(strdup(s)), // Uses malloc()
Date
void print(const String& s) { len_(strlen(str_))

P
Rect
cout << s.str_ << ": " { cout << "ctor: "; print(); }
Name & Address
<< s.len_ << endl; ~String() { cout << "dtor: "; print();
CreditCard
} free(str_); // To match malloc() in strdup()

N
Copy Constructor int main() { String s; }
Call by Value void print() { cout << "(" << str_ << ": "
Signature
// Init data members << len_ << ")" << endl; }
Data Members
s.str_ = strdup("Partha"); size_t len() { return len_; }
Free Copy & Pitfall
s.len_ = strlen(s.str_); };
Assignment Op. print(s); int main() { String s = "Partha"; // Ctor called
Copy Objects s.print();
free(s.str);
Self-Copy
} }
Signature
----- -----
Free Assignment
Partha: 6 ctor: (Partha: 6)
Comparison (Partha: 6)
Class as Type dtor: (Partha: 6)
• Note the order of initialization between str and len . What if we swap them?
Module Summary Programming in Modern C++ Partha Pratim Das M14.7
Program 14.05: A Simple String Class:
Fails for wrong order of data members
#include <iostream>
Module M14
#include <cstring>
#include <cstdlib>

L
Partha Pratim
Das using namespace std;

E
Obj. & Outlines
class String {
Obj. Lifetime size_t len_; // Swapped members cause garbage to be printed or program crash (unhandled exception)

T
String char *str_;
Date public:

P
Rect String(char *s) : str_(strdup(s)), len_(strlen(str_)) { cout << "ctor: "; print(); }
Name & Address
~String() { cout << "dtor: "; print(); free(str_); }
CreditCard
void print() { cout << "(" << str_ << ": " << len_ << ")" << endl; }

N
Copy Constructor };
Call by Value int main() { String s = "Partha";
Signature s.print();
Data Members
}
Free Copy & Pitfall
----- // May produce garbage or crash
Assignment Op. ctor: (Partha: 20)
Copy Objects (Partha: 20) // Garbage
Self-Copy dtor: (Partha: 20)
Signature
Free Assignment • len precedes str in list of data members
Comparison
• len (strlen(str )) is executed before str (strdup(s))
• When strlen(str ) is called str is still uninitialized
Class as Type • May causes the program to crash
Module Summary Programming in Modern C++ Partha Pratim Das M14.8
Practice: Program 14.06: A Simple Date Class
#include <iostream>
Module M14
using namespace std;

L
Partha Pratim
Das char monthNames[][4]={ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
char dayNames[][10] ={ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };

E
Obj. & Outlines
class Date {
Obj. Lifetime enum Month { Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec };

T
String enum Day { Mon, Tue, Wed, Thr, Fri, Sat, Sun };
Date typedef unsigned int UINT;

P
Rect UINT date_; Month month_; UINT year_;
Name & Address
public:
CreditCard
Date(UINT d, UINT m, UINT y) : date_(d), month_((Month)m), year_(y) { cout << "ctor: "; print(); }

N
Copy Constructor ~Date() { cout << "dtor: "; print(); }
Call by Value void print() { cout << date_ << "/" << monthNames[month_ - 1] << "/" << year_ << endl; }
Signature bool validDate() { /* Check validity */ return true; } // Not implemented
Data Members
Day day() { /* Compute day from date using time.h */ return Mon; } // Not implemented
Free Copy & Pitfall
};
Assignment Op. int main() {
Copy Objects Date d(30, 7, 1961);
Self-Copy d.print();
Signature }
Free Assignment
-----
Comparison ctor: 30/Jul/1961
Class as Type
30/Jul/1961
dtor: 30/Jul/1961
Module Summary Programming in Modern C++ Partha Pratim Das M14.9
Practice: Program 14.07: Point and Rect Classes:
Lifetime of Data Members or Embedded Objects
Module M14
#include <iostream> class Rect { Point TL_; Point BR_; public:
using namespace std; Rect(int tlx, int tly, int brx, int bry):
class Point { int x_; int y_; public:

L
Partha Pratim TL_(tlx, tly), BR_(brx, bry)
Das Point(int x, int y): { cout << "Rect ctor: ";
x_(x), y_(y) print(); cout << endl; }

E
Obj. & Outlines
{ cout << "Point ctor: "; ~Rect() { cout << "Rect dtor: ";
Obj. Lifetime print(); cout << endl; } print(); cout << endl; }

T
String ~Point() { cout << "Point dtor: "; void print() { cout << "["; TL_.print();
Date print(); cout << endl; } cout << " "; BR_.print(); cout << "]"; }

P
Rect void print() { cout << "(" << x_ << ", " };
Name & Address
<< y_ << ")"; } -----
CreditCard
}; Point ctor: (0, 2)

N
Copy Constructor Point ctor: (5, 7)
Call by Value int main() { Rect ctor: [(0, 2) (5, 7)]
Signature Rect r (0, 2, 5, 7);
Data Members
[(0, 2) (5, 7)]
Free Copy & Pitfall
cout << endl; r.print(); cout << endl;
Assignment Op. Rect dtor: [(0, 2) (5, 7)]
Copy Objects cout << endl; Point dtor: (5, 7)
Self-Copy } Point dtor: (0, 2)
Signature
Free Assignment
• Attempt is to construct a Rect object
Comparison • That, in turn, needs constructions of Point data members (or embedded objects) – TL and BR respectively
Class as Type
• Destruction, initiated at the end of scope of destructor’s body, naturally follows a reverse order

Module Summary Programming in Modern C++ Partha Pratim Das M14.10


Practice: Program 14.08: Name & Address Classes
#include <iostream>
Module M14
using namespace std;

L
Partha Pratim
Das #include "String.h" // Containing class String from slide 14.7
#include "Date.h"

E
Obj. & Outlines

Obj. Lifetime class Name { String firstName_, lastName_;

T
String public: Name(char* fn, char* ln) : firstName_(fn), lastName_(ln)
Date { cout << "Name ctor: "; print(); cout << endl; }

P
Rect ~Name() { cout << "Name dtor: "; print(); cout << endl; }
Name & Address
void print() { firstName_.print(); cout << " "; lastName_.print(); }
CreditCard
};

N
Copy Constructor class Address { unsigned int houseNo_;
Call by Value String street_, city_, pin_;
Signature public: Address(unsigned int hn, char* sn, char* cn, char* pin) :
Data Members
houseNo_(hn), street_(sn), city_(cn), pin_(pin)
Free Copy & Pitfall
{ cout << "Address ctor: "; print(); cout << endl; }
Assignment Op. ~Address() { cout << "Address dtor: "; print(); cout << endl; }
Copy Objects void print() {
Self-Copy cout << houseNo_ << " ";
Signature street_.print(); cout << " ";
Free Assignment
city_.print(); cout << " ";
Comparison pin_.print();
Class as Type
}
};
Module Summary Programming in Modern C++ Partha Pratim Das M14.11
Practice: Program 14.08: CreditCard Class

Module M14
class CreditCard { typedef unsigned int UINT;
char cardNumber_[17]; // 16-digit (character) card number as C-string

L
Partha Pratim Name holder_; Address addr_;
Das
Date issueDate_, expiryDate_;
UINT cvv_;

E
Obj. & Outlines
public:
Obj. Lifetime CreditCard(char* cNumber, char* fn, char* ln, unsigned int hn, char* sn, char* cn, char* pin,

T
String UINT issueMonth, UINT issueYear, UINT expiryMonth, UINT expiryYear, UINT cvv) :
Date holder_(fn, ln), addr_(hn, sn, cn, pin),

P
Rect
issueDate_(1, issueMonth, issueYear),
Name & Address
expiryDate_(1, expiryMonth, expiryYear), cvv_(cvv)
CreditCard
{ strcpy(cardNumber_, cNumber); cout << "CC ctor: "; print(); cout << endl; }

N
Copy Constructor ~CreditCard() { cout << "CC dtor: "; print(); cout << endl; }
Call by Value void print() {
Signature
cout << cardNumber_ << " "; holder_.print(); cout << " "; addr_.print(); cout << " ";
Data Members
issueDate_.print(); cout << " "; expiryDate_.print(); cout << " "; cout << cvv_;
Free Copy & Pitfall
}
Assignment Op. };
Copy Objects int main() {
Self-Copy
CreditCard cc("5321711934640027", "Sharlock", "Holmes",
Signature
221, "Baker Street", "London", "NW1 6XE", 7, 2014, 12, 2016, 811);
Free Assignment
cout << endl; cc.print(); cout << endl << endl;;
Comparison }
Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.12


Practice: Program 14.08: CreditCard Class: Lifetime Chart

Module M14
Construction of Objects typedef unsigned int UINT;
String: Sharlock class CreditCard { char cardNumber_[17];

L
Partha Pratim String: Holmes Name holder_; Address addr_;
Das Name: Sharlock Holmes Date issueDate_, expiryDate_; UINT cvv_; };
String: Baker Street class Name { String firstName_, lastName_; };

E
Obj. & Outlines
String: London class Address { unsigned int houseNo_;
Obj. Lifetime String: NW1 6XE String street_, city_, pin_; };

T
String Address: 221 Baker Street London NW1 6XE class Date { enum Month;
Date Date: 1/Jul/2014 UINT date_; Month month_; UINT year_; };

P
Rect
Date: 1/Dec/2016
Name & Address
CC: 5321711934640027 Sharlock Holmes 221 Baker Street London NW1 6XE 1/Jul/2014 1/Dec/2016 811
CreditCard
Use of Object

N
Copy Constructor 5321711934640027 Sharlock Holmes 221 Baker Street London NW1 6XE 1/Jul/2014 1/Dec/2016 811
Call by Value Destruction of Objects
Signature ~CC: 5321711934640027 Sharlock Holmes 221 Baker Street London NW1 6XE 1/Jul/2014 1/Dec/2016 811
Data Members
~Date: 1/Dec/2016
Free Copy & Pitfall
~Date: 1/Jul/2014
Assignment Op. ~Address: 221 Baker Street London NW1 6XE
Copy Objects ~String: NW1 6XE
Self-Copy ~String: London
Signature
~String: Baker Street
Free Assignment
~Name: Sharlock Holmes
Comparison ~String: Holmes
Class as Type ~String: Sharlock
Module Summary Programming in Modern C++ Partha Pratim Das M14.13
Copy Constructor

Module M14

L
Partha Pratim
Das

E
Obj. & Outlines

Obj. Lifetime

T
String
Date

P
Rect
Name & Address
CreditCard

N
Copy Constructor
Call by Value
Signature
Data Members
Free Copy & Pitfall

Assignment Op.
Copy Objects
Copy Constructor
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.14


Copy Constructor

Module M14

• We know:

L
Partha Pratim
Das
Complex c1(4.2, 5.9);

E
Obj. & Outlines

Obj. Lifetime
invokes

T
String Constructor Complex::Complex(double, double);
Date

• Which constructor is invoked for?

P
Rect
Name & Address
CreditCard Complex c2(c1);

N
Copy Constructor
Call by Value
Signature
Data Members Or for?
Free Copy & Pitfall
Complex c2 = c1;
Assignment Op.
Copy Objects • It is the Copy Constructor that takes an object of the same type and constructs a
Self-Copy
Signature copy:
Free Assignment

Comparison
Complex::Complex(const Complex &);
Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.15


Program 14.09: Complex: Copy Constructor
#include <iostream>
Module M14
#include <cmath> -----
using namespace std;

L
Partha Pratim Complex ctor: |4.2+j5.3| = 6.7624 // Ctor: c1
Das class Complex { double re_, im_; public: Complex copy ctor: |4.2+j5.3| = 6.7624 // CCtor: c2 of c1
// Constructor Complex copy ctor: |4.2+j5.3| = 6.7624 // CCtor: c3 of c2

E
Obj. & Outlines
Complex(double re, double im): |4.2+j5.3| = 6.7624 // c1
Obj. Lifetime re_(re), im_(im) |4.2+j5.3| = 6.7624 // c2

T
String { cout << "Complex ctor: "; print(); } |4.2+j5.3| = 6.7624 // c3
Date // Copy Constructor Complex dtor: |4.2+j5.3| = 6.7624 // Dtor: c3

P
Rect Complex(const Complex& c): Complex dtor: |4.2+j5.3| = 6.7624 // Dtor: c2
Name & Address
re_(c.re_), im_(c.im_) Complex dtor: |4.2+j5.3| = 6.7624 // Dtor: c1
CreditCard
{ cout << "Complex copy ctor: "; print(); }

N
Copy Constructor // Destructor
Call by Value ~Complex()
Signature { cout << "Complex dtor: "; print(); }
Data Members
double norm() { return sqrt(re_*re_ + im_*im_); }
Free Copy & Pitfall
void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
Assignment Op. };
Copy Objects int main() {
Self-Copy Complex c1(4.2, 5.3), // Constructor - Complex(double, double)
Signature c2(c1), // Copy Constructor - Complex(const Complex&)
Free Assignment
c3 = c2; // Copy Constructor - Complex(const Complex&)
Comparison

Class as Type
c1.print(); c2.print(); c3.print();
}
Module Summary Programming in Modern C++ Partha Pratim Das M14.16
Why do we need Copy Constructor?

Module M14

• Consider the function call mechanisms in C++:

L
Partha Pratim
Das
◦ Call-by-reference: Set a reference to the actual parameter as a formal parameter.

E
Obj. & Outlines
Both the formal parameter and the actual parameter share the same location
Obj. Lifetime
(object). No copy is needed

T
String
Date
◦ Return-by-reference: Set a reference to the computed value as a return value. Both

P
Rect
Name & Address the computed value and the return value share the same location (object). No copy
CreditCard
is needed

N
Copy Constructor
Call by Value ◦ Call-by-value: Make a copy or clone of the actual parameter as a formal parameter.
Signature
Data Members
This needs a Copy Constructor
Free Copy & Pitfall ◦ Return-by-value: Make a copy or clone of the computed value as a return value.
Assignment Op. This needs a Copy Constructor
Copy Objects
Self-Copy • Copy Constructor is needed for initializing the data members of a UDT from an
Signature
Free Assignment existing value
Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.17


Program 14.10: Complex: Call by value
#include <iostream>
Module M14
#include <cmath>
using namespace std;

L
Partha Pratim
Das class Complex { double re_, im_; public:
Complex(double re, double im): re_(re), im_(im) // Constructor

E
Obj. & Outlines
{ cout << "ctor: "; print(); }
Obj. Lifetime Complex(const Complex& c): re_(c.re_), im_(c.im_) // Copy Constructor

T
String { cout << "copy ctor: "; print(); }
Date ~Complex() { cout << "dtor: "; print(); }

P
Rect double norm() { return sqrt(re_*re_ + im_*im_); }
Name & Address
void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }
CreditCard
};

N
Copy Constructor void Display(Complex c_param) { // Call by value
Call by Value cout << "Display: "; c_param.print();
Signature }
Data Members
int main() { Complex c(4.2, 5.3); // Constructor - Complex(double, double)
Free Copy & Pitfall

Assignment Op. Display(c); // Copy Constructor called to copy c to c_param


Copy Objects }
Self-Copy -----
Signature ctor: |4.2+j5.3| = 6.7624 // Ctor of c in main()
Free Assignment
copy ctor: |4.2+j5.3| = 6.7624 // Ctor c_param as copy of c, call Display()
Comparison Display: |4.2+j5.3| = 6.7624 // c_param
Class as Type
dtor: |4.2+j5.3| = 6.7624 // Dtor c_param on exit from Display()
dtor: |4.2+j5.3| = 6.7624 // Dtor of c on exit from main()
Module Summary Programming in Modern C++ Partha Pratim Das M14.18
Signature of Copy Constructors

Module M14
• Signature of a Copy Constructor can be one of:

L
Partha Pratim
Das
MyClass(const MyClass& other); // Common

E
Obj. & Outlines // Source cannot be changed
Obj. Lifetime
MyClass(MyClass& other); // Occasional

T
String
// Source needs to change. Like in smart pointers
Date MyClass(volatile const MyClass& other); // Rare
MyClass(volatile MyClass& other); // Rare

P
Rect
Name & Address
CreditCard
• None of the following are copy constructors, though they can copy:

N
Copy Constructor
Call by Value
MyClass(MyClass* other);
Signature
MyClass(const MyClass* other);
Data Members
Free Copy & Pitfall

Assignment Op. • Why the parameter to a copy constructor must be passed as Call-by-Reference?
Copy Objects
Self-Copy MyClass(MyClass other);
Signature
Free Assignment

Comparison
The above is an infinite recursion of copy calls as the call to copy constructor itself
Class as Type needs to make copy for the Call-by-Value mechanism
Module Summary Programming in Modern C++ Partha Pratim Das M14.19
Program 14.11: Point and Rect Classes: Embedded Objects
Default, Copy and Overloaded Constructors
#include <iostream>
Module M14
using namespace std;
class Point { int x_; int y_; public:

L
Partha Pratim
Das Point(int x, int y): x_(x), y_(y) { cout << "Point ctor: "; print(); cout << endl; } // Ctor
Point(): x_(0), y_(0) { cout << "Point ctor: "; print(); cout << endl; } // DCtor

E
Obj. & Outlines
Point(const Point& p): x_(p.x_), y_(p.y_) { cout << "Point cctor: "; print(); cout << endl; } // CCtor
Obj. Lifetime ~Point() { cout << "Point dtor: "; print(); cout << endl; } // Dtor

T
String void print() { cout << "(" << x_ << ", " << y_ << ")"; } }; // Class Point
Date class Rect { Point TL_; Point BR_; public:

P
Rect Rect(int tlx, int tly, int brx, int bry): TL_(tlx, tly), BR_(brx, bry) // Ctor of Rect: 4 coords
Name & Address
{ cout << "Rect ctor: "; print(); cout << endl; } // Uses Ctor for Point
CreditCard
Rect(const Point& p_tl, const Point& p_br): TL_(p_tl), BR_(p_br) // Ctor of Rect: 2 Points

N
Copy Constructor { cout << "Rect ctor: "; print(); cout << endl; } // Uses CCtor for Point
Call by Value Rect(const Point& p_tl, int brx, int bry): TL_(p_tl), BR_(brx, bry) // Ctor of Rect: Point + 2 coords
Signature { cout << "Rect ctor: "; print(); cout << endl; } // Uses CCtor for Point
Data Members
Rect() { cout << "Rect ctor: "; print(); cout << endl; } // DCtor of Rect: // DCtor Point
Free Copy & Pitfall
Rect(const Rect& r): TL_(r.TL_), BR_(r.BR_) // CCtor of Rect
Assignment Op. { cout << "Rect cctor: "; print(); cout << endl; } // Uses CCtor for Point
Copy Objects ~Rect() { cout << "Rect dtor: "; print(); cout << endl; } // Dtor
Self-Copy void print() { cout << "["; TL_.print(); cout << " "; BR_.print(); cout << "]"; } }; // Class Rect
Signature
Free Assignment • When parameter (tlx, tly) is set to TL by TL (tlx, tly): parameterized Ctor of Point is invoked
Comparison • When parameter p tl is set to TL by TL (p tl): CCtor of Point is invoked
• When TL is set by default in DCtor of Rect: DCtor of Point is invoked
Class as Type
• When member r.TL is set to TL by TL (r.TL ) in CCtor of Rect: CCtor of Point is invoked
Module Summary Programming in Modern C++ Partha Pratim Das M14.20
Practice: Program 14.11: Rect Class: Trace of Object Lifetimes
Code Output Lifetime Remarks
Module M14
int main() {
Rect r1(0, 2, 5, 7); Point ctor: (0, 2) Point r1.TL

L
Partha Pratim //Rect(int, int, int, int) Point ctor: (5, 7) Point r1.BR
Das Rect ctor: [(0, 2) (5, 7)] Rect r1
Rect r2(Point(3, 5), Point ctor: (6, 9) Point t1 Second parameter

E
Obj. & Outlines Point(6, 9)); Point ctor: (3, 5) Point t2 First parameter
//Rect(Point&, Point&) Point cctor: (3, 5) r2.TL = t2 Copy to r2.TL
Obj. Lifetime Point cctor: (6, 9) r2.BR = t1 Copy to r2.BR

T
String Rect ctor: [(3, 5) (6, 9)] Rect r2
Point dtor: (3, 5) ˜Point t2 First parameter
Date
Point dtor: (6, 9) ˜Point t1 Second parameter

P
Rect Rect r3(Point(2, 2), 6, 4); Point ctor: (2, 2) Point t3 First parameter
Name & Address //Rect(Point&, int, int) Point cctor: (2, 2) r3.TL = t3 Copy to r3.TL
CreditCard Point ctor: (6, 4) Point r3.BR

N
Rect ctor: [(2, 2) (6, 4)] Rect r3
Copy Constructor Point dtor: (2, 2) ˜Point t3 First parameter
Call by Value Rect r4; Point ctor: (0, 0) Point r4.TL
Signature
//Rect() Point ctor: (0, 0) Point r4.BR
Rect ctor: [(0, 0) (0, 0)] Rect r4
Data Members
return 0; Rect dtor: [(0, 0) (0, 0)] ˜Rect r4
Free Copy & Pitfall } Point dtor: (0, 0) ˜Point r4.BR
Point dtor: (0, 0) ˜Point r4.TL
Assignment Op.
Rect dtor: [(2, 2) (6, 4)] ˜Rect r3
Copy Objects Point dtor: (6, 4) ˜Point r3.BR
Self-Copy Point dtor: (2, 2) ˜Point r3.TL
Signature Rect dtor: [(3, 5) (6, 9)] ˜Rect r2
Point dtor: (6, 9) ˜Point r2.BR
Free Assignment
Point dtor: (3, 5) ˜Point r2.TL
Comparison Rect dtor: [(0, 2) (5, 7)] ˜Rect r1
Point dtor: (5, 7) ˜Point r1.BR
Class as Type Point dtor: (0, 2) ˜Point r1.TL

Module Summary Programming in Modern C++ Partha Pratim Das M14.21


Free Copy Constructor

Module M14
• If no copy constructor is provided by the user, the compiler supplies a free one
• Free copy constructor cannot initialize the object to proper values. It performs Shallow Copy

L
Partha Pratim
Das • Shallow Copy aka bit-wise copy, field-by-field copy, field-for-field copy, or field copy
◦ An object is created by simply copying the data of all variables of the original object

E
Obj. & Outlines

Obj. Lifetime ◦ Works well if none of the variables of the object are defined in heap / free store

T
String
◦ For dynamically created variables, the copied object refers to the same memory location
Date
◦ Creates ambiguity (changing one changes the copy) and run-time errors (dangling pointer)

P
Rect
Name & Address
CreditCard
• Deep Copy or its variants Lazy Copy and Copy-on-Write

N
Copy Constructor ◦ An object is created by copying data of all variables except the ones on heap
Call by Value
Signature
◦ Allocates similar memory resources with the same value to the object
Data Members ◦ Need to explicitly define the copy constructor and assign dynamic memory as required
Free Copy & Pitfall
◦ Required to dynamically allocate memory to the variables in the other constructors
Assignment Op.
Copy Objects
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.22


Pitfalls of Bit-wise Copy: Shallow Copy

Module M14 • Consider a class:


class A { int i_; // Non-pointer data member

L
Partha Pratim
Das int* p_; // Pointer data member
public:

E
Obj. & Outlines A(int i, int j) : i_(i), p_(new int(j)) { } // Init. with pointer to dynamically created object
Obj. Lifetime
~A() { cout << "Destruct " << this << ": "; // Object identity

T
String
cout << "i_ = " << i_ << " p_ = " << p_ << " *p = " << *p_ << endl; // Object state
Date
delete p_; // Release resource
}

P
Rect
Name & Address };
CreditCard
• As no copy constructor is provided, the implicit copy constructor does a bit-wise copy. So

N
Copy Constructor
Call by Value when an A object is copied, p is copied and continues to point to the same dynamic int:
Signature int main() { A a1(2, 3); A a2(a1); // Construct a2 as a copy of a1. Done by bit-wise copy
Data Members cout << "&a1 = " << &a1 << " &a2 = " << &a2 << endl;
Free Copy & Pitfall
}
Assignment Op.
Copy Objects • The output is wrong, as a1.p = a2.p points to the same int location. Once a2 is destructed,
Self-Copy
a2.p is released, and a1.p becomes dangling. The program may print garbage or crash:
Signature
Free Assignment
&a1 = 008FF838 &a2 = 008FF828 // Identities of objects
Destruct 008FF828: i_ = 2 p_ = 00C15440 *p = 3 // Dtor of a2. Note that a2.p_ = a1.p_
Comparison
Destruct 008FF838: i_ = 2 p_ = 00C15440 *p = -17891602 // Dtor of a1. a1.p_=a2.p_ points to garbage
Class as Type

Module Summary
• The bit-wise copy of members is known as Shallow Copy
Programming in Modern C++ Partha Pratim Das M14.23
Pitfalls of Bit-wise Copy: Deep Copy

Module M14 • Now suppose we provide a user-defined copy constructor:


class A { int i_; // Non-pointer data member

L
Partha Pratim
Das int* p_; // Pointer data member
public:

E
Obj. & Outlines A(int i, int j) : i_(i), p_(new int(j)) { } // Init. with pointer to dynamically created object
Obj. Lifetime
A(const A& a) : i_(a.i_), // Copy Constructor
p_(new int(*a.p_)) { }

T
String
// Allocation done and value copied - Deep Copy
Date
~A() { cout << "Destruct " << this << ": "; // Object identity
cout << "i_ = " << i_ << " p_ = " << p_ << " *p = " << *p_ << endl; // Object state

P
Rect
Name & Address delete p_; // Release resource
CreditCard }

N
Copy Constructor
};
Call by Value
Signature
• The output now is correct, as a1.p 6= a2.p points to the different int locations with the
Data Members values *a1.p = *a2.p properly copied:
Free Copy & Pitfall &a1 = 00B8F9E0 &a2 = 00B8F9D0 // Identities of objects
Assignment Op. Destruct 00B8F9D0: i_ = 2 p_ = 00C95480 *p = 3 // Dtor of a2. a2.p_ is different from a1.p_
Copy Objects Destruct 00B8F9E0: i_ = 2 p_ = 00C95440 *p = 3 // Dtor of a1. Works correctly!
Self-Copy
Signature
• This is known as Deep Copy where every member is copied properly. Note that:
Free Assignment
◦ In every class, provide copy constructor to adopt to deep copy which is always safe
Comparison
◦ Naturally, shallow copy is cheaper than deep copy. So some languages support variants as
Class as Type
Lazy Copy or Copy-on-Write for efficiency
Module Summary Programming in Modern C++ Partha Pratim Das M14.24
Practice: Program 14.12: Complex: Free Copy Constructor
#include <iostream>
Module M14
#include <cmath>
using namespace std;

L
Partha Pratim
Das class Complex { double re_, im_; public:
Complex(double re, double im) : re_(re), im_(im) { cout << "ctor: "; print(); } // Ctor

E
Obj. & Outlines
// Complex(const Complex& c) : re_(c.re_), im_(c.im_) { cout<<"copy ctor: "; print(); } // CCtor: Free only
Obj. Lifetime ~Complex() { cout << "dtor: "; print(); } // Dtor

T
String double norm() { return sqrt(re_*re_ + im_*im_); }
Date void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; }

P
Rect };
Name & Address
void Display(Complex c_param) { cout << "Display: "; c_param.print(); }
CreditCard
int main() { Complex c(4.2, 5.3); // Constructor - Complex(double, double)

N
Copy Constructor Display(c); // Free Copy Constructor called to copy c to c_param
Call by Value }
Signature User-defined CCtor Free CCtor
Data Members ctor: |4.2+j5.3| = 6.7624 ctor: |4.2+j5.3| = 6.7624
Free Copy & Pitfall copy ctor: |4.2+j5.3| = 6.7624 No message from free CCtor
Assignment Op. Display: |4.2+j5.3| = 6.7624 Display: |4.2+j5.3| = 6.7624
Copy Objects dtor: |4.2+j5.3| = 6.7624 dtor: |4.2+j5.3| = 6.7624
Self-Copy dtor: |4.2+j5.3| = 6.7624 dtor: |4.2+j5.3| = 6.7624
Signature
Free Assignment • User has provided no copy constructor
Comparison • Compiler provides free copy constructor
• Compiler-provided copy constructor performs bit-wise copy - hence there is no message
Class as Type
• Correct in this case as members are of built-in type and there is no dynamically allocated data
Module Summary Programming in Modern C++ Partha Pratim Das M14.25
Practice: Program 14.13: String: User-defined Copy Constructor
#include <iostream>
Module M14
#include <cstdlib>
#include <cstring>

L
Partha Pratim
Das using namespace std;
class String { public: char *str_; size_t len_;

E
Obj. & Outlines
String(char *s) : str_(strdup(s)), len_(strlen(str_)) { } // Ctor
Obj. Lifetime String(const String& s) : str_(strdup(s.str_)), len_(s.len_) { } // CCtor: User provided

T
String ~String() { free(str_); } // Dtor
Date void print() { cout << "(" << str_ << ": " << len_ << ")" << endl; }

P
Rect };
Name & Address
void strToUpper(String a) { // Make the string uppercase
CreditCard
for (int i = 0; i < a.len_; ++i) { a.str_[i] = toupper(a.str_[i]); }

N
Copy Constructor cout << "strToUpper: "; a.print();
Call by Value } // a.~String() is invoked releasing a.str_. s.str_ remains intact
Signature int main() { String s = "Partha"; s.print(); strToUpper(s); s.print(); }
Data Members
---
Free Copy & Pitfall
(Partha: 6)
Assignment Op. strToUpper: (PARTHA: 6)
Copy Objects (Partha: 6)
Self-Copy
Signature • User has provided copy constructor. So Compiler does not provide free copy constructor
Free Assignment • When actual parameter s is copied to formal parameter a, space is allocated for a.str and then it is copied from
Comparison s.str . On exit from strToUpper, a is destructed and a.str is deallocated. But in main, s remains intact and access
to s.str is valid.
Class as Type
• Deep Copy: While copying the object, the pointed object is copied in a fresh allocation. This is safe
Module Summary Programming in Modern C++ Partha Pratim Das M14.26
Practice: Program 14.14: String: Free Copy Constructor
#include <iostream>
Module M14 #include <cstring>
#include <cstdlib>

L
Partha Pratim
Das using namespace std;
class String { public: char *str_; size_t len_;

E
Obj. & Outlines String(char *s) : str_(strdup(s)), len_(strlen(str_)) { } // Ctor
Obj. Lifetime
// String(const String& s) : str_(strdup(s.str_)), len_(s.len_) { } // CCtor: Free only

T
String
~String() { free(str_); } // Dtor
Date void print() { cout << "(" << str_ << ": " << len_ << ")" << endl; }
};

P
Rect
Name & Address void strToUpper(String a) { // Make the string uppercase
CreditCard for (int i = 0; i < a.len_; ++i) { a.str_[i] = toupper(a.str_[i]); } cout<<"strToUpper: "; a.print();

N
Copy Constructor } // a.~String() is invoked releasing a.str_ and invalidating s.str_ = a.str_
Call by Value
int main() { String s = "Partha"; s.print(); strToUpper(s); s.print(); } // Last print fails
Signature
Data Members
User-defined CCtor Free CCtor
Free Copy & Pitfall
(Partha: 6) (Partha: 6)
strToUpper: (PARTHA: 6) strToUpper: (PARTHA: 6)
Assignment Op. (Partha: 6) (?????????????????????????????: 6)
Copy Objects
Self-Copy • User has provided no copy constructor. Compiler provides free copy constructor
Signature • Free copy constructor performs bit-copy - hence no allocation is done for str when actual parameter s is copied to
Free Assignment
formal parameter a. s.str is merely copied to a.str and both continue to point to the same memory. On exit from
Comparison strToUpper, a is destructed and a.str is deallocated. Hence in main access to s.str is dangling. Program prints
Class as Type
garbage and / or crashes
• Shallow Copy: With bit-copy, only the pointer is copied - not the pointed object. This is risky
Module Summary Programming in Modern C++ Partha Pratim Das M14.27
Copy Assignment Operator

Module M14

L
Partha Pratim
Das

E
Obj. & Outlines

Obj. Lifetime

T
String
Date

P
Rect
Name & Address
CreditCard

N
Copy Constructor
Call by Value
Signature
Data Members
Free Copy & Pitfall

Assignment Op.
Copy Objects
Copy Assignment Operator
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.28


Copy Assignment Operator

Module M14

• We can copy an existing object to another existing object as

L
Partha Pratim
Das
Complex c1 = (4.2, 5.9), c2(5.1, 6.3);

E
Obj. & Outlines

Obj. Lifetime
c2 = c1; // c1 becomes { 4.2, 5.9 }

T
String
Date

P
Rect
Name & Address
CreditCard This is like normal assignment of built-in types and overwrites the old value with the

N
Copy Constructor new value
Call by Value
Signature • It is the Copy Assignment that takes an object of the same type and overwrites into
Data Members
Free Copy & Pitfall
an existing one, and returns that object:
Assignment Op. Complex::Complex& operator= (const Complex &);
Copy Objects
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.29


Program 14.15: Complex: Copy Assignment
#include <iostream>
Module M14 #include <cmath>
using namespace std;

L
Partha Pratim
Das class Complex { double re_, im_; public:
Complex(double re, double im) : re_(re), im_(im) { cout << "ctor: "; print(); } // Ctor

E
Obj. & Outlines Complex(const Complex& c) : re_(c.re_), im_(c.im_) { cout << "cctor: "; print(); } // CCtor
Obj. Lifetime
~Complex() { cout << "dtor: "; print(); } // Dtor

T
String
Complex& operator=(const Complex& c) // Copy Assignment Operator
Date { re_ = c.re_; im_ = c.im_; cout << "copy: "; print(); return *this; } // Return *this for chaining
double norm() { return sqrt(re_*re_ + im_*im_); }

P
Rect
Name & Address void print() { cout << "|" << re_ << "+j" << im_ << "| = " << norm() << endl; } }; // Class Complex
CreditCard int main() { Complex c1(4.2, 5.3), c2(7.9, 8.5); Complex c3(c2); // c3 Copy Constructed from c2

N
Copy Constructor c1.print(); c2.print(); c3.print();
Call by Value
c2 = c1; c2.print(); // Copy Assignment Operator
Signature c1 = c2 = c3; c1.print(); c2.print(); c3.print(); // Copy Assignment Chain
Data Members }
Free Copy & Pitfall ctor: |4.2+j5.3| = 6.7624 // c1 - ctor copy: |7.9+j8.5| = 11.6043 // c2 <- c3
ctor: |7.9+j8.5| = 11.6043 // c2 - ctor copy: |7.9+j8.5| = 11.6043 // c1 <- c2
Assignment Op.
cctor: |7.9+j8.5| = 11.6043 // c3 - ctor |7.9+j8.5| = 11.6043 // c1
Copy Objects
Self-Copy
|4.2+j5.3| = 6.7624 // c1 |7.9+j8.5| = 11.6043 // c2
Signature
|7.9+j8.5| = 11.6043 // c2 |7.9+j8.5| = 11.6043 // c3
Free Assignment |7.9+j8.5| = 11.6043 // c3 dtor: |7.9+j8.5| = 11.6043 // c3 - dtor
copy: |4.2+j5.3| = 6.7624 // c2 <- c1 dtor: |7.9+j8.5| = 11.6043 // c2 - dtor
Comparison
|4.2+j5.3| = 6.7624 // c2 dtor: |7.9+j8.5| = 11.6043 // c1 - dtor
Class as Type
• Copy assignment operator should return the object to make chain assignments possible
Module Summary Programming in Modern C++ Partha Pratim Das M14.30
Program 14.16: String: Copy Assignment
#include <iostream>
Module M14
#include <cstring>
#include <cstdlib>

L
Partha Pratim
Das using namespace std;
class String { public: char *str_; size_t len_;

E
Obj. & Outlines
String(char *s) : str_(strdup(s)), len_(strlen(str_)) { } // Ctor
Obj. Lifetime String(const String& s) : str_(strdup(s.str_)), len_(s.len_) { } // CCtor

T
String ~String() { free(str_); } // Dtor
Date String& operator=(const String& s) { // Copy Assignment Operator

P
Rect free(str_); // Release existing memory
Name & Address
str_ = strdup(s.str_); // Perform deep copy
CreditCard
len_ = s.len_; // Copy data member of built-in type

N
Copy Constructor return *this; // Return object for chain assignment
Call by Value }
Signature void print() { cout << "(" << str_ << ": " << len_ << ")" << endl; }
Data Members
};
Free Copy & Pitfall
int main() { String s1 = "Football", s2 = "Cricket"; s1.print(); s2.print(); s2 = s1; s2.print(); }
Assignment Op. ---
Copy Objects (Football: 8)
Self-Copy (Cricket: 7)
Signature (Football: 8)
Free Assignment • In copy assignment operator, str = s.str should not be done for two reasons:
Comparison 1) Resource held by str will leak
2) Shallow copy will result with its related issues
Class as Type
• What happens if a self-copy s1 = s1 is done?
Module Summary Programming in Modern C++ Partha Pratim Das M14.31
Program 14.17: String: Self Copy
#include <iostream>
Module M14
#include <cstring>
#include <cstdlib>

L
Partha Pratim
Das using namespace std;
class String { public: char *str_; size_t len_;

E
Obj. & Outlines
String(char *s) : str_(strdup(s)), len_(strlen(str_)) { } // Ctor
Obj. Lifetime String(const String& s) : str_(strdup(s.str_)), len_(s.len_) { } // CCtor

T
String ~String() { free(str_); } // Dtor
Date String& operator=(const String& s) { // Copy Assignment Operator

P
Rect free(str_); // Release existing memory
Name & Address
str_ = strdup(s.str_); // Perform deep copy
CreditCard • For self-copy
len_ = s.len_; // Copy data member of built-in type

N
Copy Constructor return *this; // Return object for chain assignment
Call by Value }
Signature void print() { cout << "(" << str_ << ": " << len_ << ")" << endl; }
Data Members
};
Free Copy & Pitfall
int main() { String s1 = "Football", s2 = "Cricket"; s1.print(); s2.print(); s1 = s1; s1.print(); }
Assignment Op. ---
Copy Objects (Football: 8)
Self-Copy (Cricket: 7)
Signature (????????: 8) // Garbage is printed. May crash too
Free Assignment

Comparison • Hence, free(str ) first releases the memory, and then strdup(s.str ) tries to copy from released memory
• This may crash or produce garbage values
Class as Type
• Self-copy must be detected and guarded
Module Summary Programming in Modern C++ Partha Pratim Das M14.32
Program 14.18: String: Self Copy: Safe
#include <iostream>
Module M14
#include <cstring>
#include <cstdlib>

L
Partha Pratim
Das using namespace std;
class String { public: char *str_; size_t len_;

E
Obj. & Outlines
String(char *s) : str_(strdup(s)), len_(strlen(str_)) { } // Ctor
Obj. Lifetime String(const String& s) : str_(strdup(s.str_)), len_(s.len_) { } // CCtor

T
String ~String() { free(str_); } // Dtor
Date String& operator=(const String& s) { // Copy Assignment Operator

P
Rect if (this != &s) { // Check if the source and destination are same
Name & Address
free(str_);
CreditCard
str_ = strdup(s.str_);
• Check for se

N
Copy Constructor len_ = s.len_;
Call by Value }
Signature return *this;
Data Members
}
Free Copy & Pitfall
void print() { cout << "(" << str_ << ": " << len_ << ")" << endl; }
Assignment Op. };
Copy Objects int main() { String s1 = "Football", s2 = "Cricket"; s1.print(); s2.print(); s1 = s1; s1.print(); }
Self-Copy ---
Signature (Football: 8)
Free Assignment
(Cricket: 7)
Comparison (Football: 8)
Class as Type
• In case of self-copy, do nothing
Module Summary Programming in Modern C++ Partha Pratim Das M14.33
Signature and Body of Copy Assignment Operator

Module M14 • For class MyClass, typical copy assignment operator will be:

L
Partha Pratim MyClass& operator=(const MyClass& s) {
Das
if (this != &s) { // Check if the source and destination are same
// Release resources held by *this

E
Obj. & Outlines
// Copy members of s to members of *this
Obj. Lifetime }

T
String
return *this; // Return object for chain assignment
Date
}

P
Rect
Name & Address
CreditCard • Signature of a Copy Assignment Operator can be one of:

N
Copy Constructor
Call by Value
MyClass& operator=(const MyClass& rhs); // Common. No change in Source
Signature
MyClass& operator=(MyClass& rhs); // Occasional. Change in Source
Data Members
Free Copy & Pitfall • The following Copy Assignment Operators are occasionally used:
Assignment Op.
Copy Objects MyClass& operator=(MyClass rhs);
Self-Copy const MyClass& operator=(const MyClass& rhs);
Signature const MyClass& operator=(MyClass& rhs);
Free Assignment const MyClass& operator=(MyClass rhs);
Comparison MyClass operator=(const MyClass& rhs);
MyClass operator=(MyClass& rhs);
Class as Type
MyClass operator=(MyClass rhs);
Module Summary Programming in Modern C++ Partha Pratim Das M14.34
Free Assignment Operator

Module M14

• If no copy assignment operator is provided / overloaded by the user, the compiler

L
Partha Pratim
Das
supplies a free one

E
Obj. & Outlines
• Free copy assignment operator cannot copy the object with proper values. It performs
Obj. Lifetime
Shallow Copy

T
String
Date
• In every class, provide copy assignment operator to adopt to deep copy which is always

P
Rect
Name & Address
CreditCard
safe

N
Copy Constructor
Call by Value
Signature
Data Members
Free Copy & Pitfall

Assignment Op.
Copy Objects
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.35


Comparison of Copy Constructor and Copy Assignment Operator

Module M14

L
Partha Pratim
Das

E
Obj. & Outlines

Obj. Lifetime

T
String
Date

P
Rect
Name & Address
CreditCard

N
Copy Constructor
Call by Value
Signature
Data Members
Free Copy & Pitfall

Assignment Op.
Copy Objects
Comparison of Copy Constructor and Copy Assignment
Self-Copy
Signature
Operator
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.36


Comparison of Copy Constructor and Copy Assignment Operator

Module M14
Copy Constructor Copy Assignment Operator

L
Partha Pratim
Das

• An overloaded constructor • An operator overloading

E
Obj. & Outlines

Obj. Lifetime • Initializes a new object with an existing • Assigns the value of one existing object

T
String
Date
object to another existing object
• Used when a new object is created with • Used when we want to assign existing

P
Rect
Name & Address
CreditCard some existing object object to another object

N
Copy Constructor • Needed to support call-by-value and
Call by Value
Signature return-by-value
Data Members
Free Copy & Pitfall
• Newly created object use new memory • Memory location of destination object
Assignment Op.
location is reused with pointer variables being re-
Copy Objects leased and reallocated
Self-Copy
Signature • Care is needed for self-copy
Free Assignment
• If not defined in the class, the compiler • If not overloaded, the compiler provides
Comparison
provides one with bitwise copy one with bitwise copy
Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.37


Class as a Data-type

Module M14

L
Partha Pratim
Das

E
Obj. & Outlines

Obj. Lifetime

T
String
Date

P
Rect
Name & Address
CreditCard

N
Copy Constructor
Call by Value
Signature
Data Members
Free Copy & Pitfall

Assignment Op.
Copy Objects
Class as a Data-type
Self-Copy
Signature
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.38


Class as a Data-type

Module M14 • We add the copy construction and assignment to a class being a composite data type in C++

L
Partha Pratim
Das
// declare i to be of int type // declare c to be of Complex type

E
Obj. & Outlines int i; Complex c;
Obj. Lifetime
// initialise i

T
String // initialise the real and imaginary components of c
int i = 5; Complex c = (4, 5); // Ctor
Date
int j = i; Complex c1 = c; // CCtor

P
Rect
Name & Address
int k(j); Complex c2(c1); // CCtor
CreditCard

N
// print i // print the real and imaginary components of c
Copy Constructor
cout << i; cout << c.re << c.im;
Call by Value
Signature
OR c.print(); // Method Complex::print() defined for printing
Data Members
OR cout << c; // operator<<() overloaded for printing
Free Copy & Pitfall
// add two ints // add two Complex objects
Assignment Op.
int i = 5, j = 6; Complex c1 = (4, 5), c2 = (4, 6);
Copy Objects
i+j; c1.add(c2); // Method Complex::add() defined to add
Self-Copy
Signature
OR c1+c2; // operator+() overloaded to add
Free Assignment
// copy value of i to j // copy value of one Complex object to another
Comparison int i = 5, j; Complex c1 = (4, 5), c2 = (4, 6);
Class as Type
j = i; c2 = c1; // c2.re <- c1.re and c2.im <- c1.im by copy assignment
Module Summary Programming in Modern C++ Partha Pratim Das M14.39
Module Summary

Module M14

• Copy Constructors

L
Partha Pratim
Das
◦ A new object is created

E
Obj. & Outlines
◦ The new object is initialized with the value of data members of another object
Obj. Lifetime

T
String • Copy Assignment Operator
Date
◦ An object is already existing (and initialized)

P
Rect
Name & Address
CreditCard
◦ The members of the existing object are replaced by values of data members of

N
Copy Constructor another object
Call by Value
Signature
◦ Care is needed for self-copy
Data Members
Free Copy & Pitfall
• Deep and Shallow Copy for Pointer Members
Assignment Op. ◦ Deep copy allocates new space for the contents and copies the pointed data
Copy Objects
Self-Copy
◦ Shallow copy merely copies the pointer value – hence, the new copy and the original
Signature pointer continue to point to the same data
Free Assignment

Comparison

Class as Type

Module Summary Programming in Modern C++ Partha Pratim Das M14.40


Module M15

L
Partha Pratim
Das
Programming in Modern C++

E
Objectives &
Outlines
Module M15: Const-ness

T
const Objects
Example

P
const Member
Functions
Example Partha Pratim Das

N
const Data
Members
Example Department of Computer Science and Engineering
Credit Card Indian Institute of Technology, Kharagpur
String
Date ppd@cse.iitkgp.ac.in
Name
Address
CreditClass
All url’s in this module have been accessed in September, 2021 and found to be functional
mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.1
Module Recap

Module M15

• Copy Constructors

L
Partha Pratim
Das
◦ A new object is created

E
Objectives &
Outlines ◦ The new object is initialized with the value of data members of another object

T
const Objects • Copy Assignment Operator
Example

◦ An object is already existing (and initialized)

P
const Member
Functions
Example
◦ The members of the existing object are replaced by values of data members of

N
const Data another object
Members
Example
◦ Care is needed for self-copy
Credit Card
String
• Deep and Shallow Copy for Pointer Members
Date
Name
◦ Deep copy allocates new space for the contents and copies the pointed data
Address ◦ Shallow copy merely copies the pointer value – hence, the new copy and the original
CreditClass
pointer continue to point to the same data
mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.2
Module Objectives

Module M15

• Understand const-ness of objects in C++

L
Partha Pratim
Das
• Understand the use of const-ness in class design

E
Objectives &
Outlines

T
const Objects
Example

P
const Member
Functions
Example

N
const Data
Members
Example
Credit Card
String
Date
Name
Address
CreditClass

mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.3
Module Outline

Module M15
1 Constant Objects

L
Partha Pratim
Das Simple Example

E
Objectives & 2 Constant Member Functions
Outlines
Simple Example

T
const Objects
Example
3 Constant Data Members

P
const Member
Functions Simple Example
Example
Credit Card Example: Putting it all together

N
const Data
Members
String
Example
Date
Credit Card Name
String
Address
Date
Name
CreditClass
Address
CreditClass
4 mutable Members
mutable Simple Example
Members
Example
mutable Guidelines
mutable Guidelines
5 Module Summary
Module Summary
Programming in Modern C++ Partha Pratim Das M15.4
Constant Objects

Module M15

L
Partha Pratim
Das

E
Objectives &
Outlines

T
const Objects
Example

P
const Member
Functions
Example

N
const Data
Members
Example
Credit Card
String
Date
Name
Address
Constant Objects
CreditClass

mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.5
Constant Objects

Module M15 • Like objects of built-in type, objects of user-defined types can also be made constant
• If an object is constant, none of its data members can be changed

L
Partha Pratim
Das

• The type of the this pointer of a constant object of class, say, MyClass is:

E
Objectives &
Outlines

T
const Objects
Example // const Pointer to const Object
const MyClass * const this;

P
const Member
Functions
Example

N
const Data
Members
instead of
Example
Credit Card
String // const Pointer to non-const Object
Date
Name
MyClass * const this;
Address
CreditClass

mutable
as for a non-constant object of the same class
Members
Example • A constant objects cannot invoke normal methods of the class lest these methods
mutable Guidelines
change the object
Module Summary
Programming in Modern C++ Partha Pratim Das M15.6
Program 15.01: Non-Constant Objects

Module M15 #include <iostream>


using namespace std;

L
Partha Pratim
Das class MyClass { int myPriMember_;
public: int myPubMember_;

E
Objectives & MyClass(int mPri, int mPub) : myPriMember_(mPri), myPubMember_(mPub) { }
Outlines
int getMember() { return myPriMember_; }

T
const Objects void setMember(int i) { myPriMember_ = i; }
Example void print() { cout << myPriMember_ << ", " << myPubMember_ << endl; }
};

P
const Member
Functions int main() { MyClass myObj(0, 1); // Non-constant object
Example

N
const Data
cout << myObj.getMember() << endl;
Members myObj.setMember(2);
Example myObj.myPubMember_ = 3;
Credit Card myObj.print();
String }
Date ---
Name
0
Address
2, 3
CreditClass

mutable • It is okay to invoke methods for non-constant object myObj


Members • It is okay to make changes in non-constant object myObj by method (setMember())
Example • It is okay to make changes in non-constant object myObj directly (myPubMember )
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.7
Program 15.02: Constant Objects
#include <iostream>
Module M15
using namespace std;

L
Partha Pratim
Das class MyClass { int myPriMember_; public: int myPubMember_;
MyClass(int mPri, int mPub) : myPriMember_(mPri), myPubMember_(mPub) { }

E
Objectives &
Outlines
int getMember() { return myPriMember_; }
void setMember(int i) { myPriMember_ = i; }

T
const Objects void print() { cout << myPriMember_ << ", " << myPubMember_ << endl; }
Example
};

P
const Member int main() { const MyClass myConstObj(5, 6); // Constant object
Functions
Example
cout << myConstObj.getMember() << endl; // Error 1

N
const Data myConstObj.setMember(7); // Error 2
Members myConstObj.myPubMember_ = 8; // Error 3
Example myConstObj.print(); // Error 4
Credit Card
}
String
Date
• It is not allowed to invoke methods or make changes in constant object myConstObj
Name
Address
• Error (1, 2 & 4) on method invocation typically is:
CreditClass
cannot convert ’this’ pointer from ’const MyClass’ to ’MyClass &’
• Error (3) on member update typically is:
mutable
Members
’myConstObj’ : you cannot assign to a variable that is const
Example
• With const, this pointer is const MyClass * const while the methods expects MyClass * const
mutable Guidelines • Consequently, we cannot print the data member of the class (even without changing it)
• Fortunately, constant objects can invoke (select) methods if they are constant member functions
Module Summary
Programming in Modern C++ Partha Pratim Das M15.8
Constant Member Functions

Module M15

L
Partha Pratim
Das

E
Objectives &
Outlines

T
const Objects
Example

P
const Member
Functions
Example

N
const Data
Members
Example
Credit Card
String
Date
Name
Address
Constant Member Functions
CreditClass

mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.9
Constant Member Function

Module M15 • To declare a constant member function, we use the keyword const between the function
header and the body. Like:

L
Partha Pratim
Das
void print() const { cout << myMember_ << endl; }

E
Objectives &
Outlines
• A constant member function expects a this pointer as:

T
const Objects
Example const MyClass * const this;

P
const Member
Functions
and hence can be invoked by constant objects
Example • In a constant member function no data member can be changed. Hence,

N
const Data
Members void setMember(int i) const
Example { myMember_ = i; } // data member cannot be changed
Credit Card
String
Date gives an error
Name
Address • Interesting, non-constant objects can invoke constant member functions (by casting –
CreditClass
we discuss later) and, of course, non-constant member functions
mutable
Members • Constant objects, however, can only invoke constant member functions
Example
mutable Guidelines
• All member functions that do not need to change an object must be declared as
Module Summary
constant member functions
Programming in Modern C++ Partha Pratim Das M15.10
Program 15.03: Constant Member Functions
#include <iostream>
Module M15
using namespace std;
class MyClass { int myPriMember_; public: int myPubMember_;

L
Partha Pratim
Das MyClass(int mPri, int mPub) : myPriMember_(mPri), myPubMember_(mPub) { }
int getMember() const { return myPriMember_; } // const Member Func.

E
Objectives &
Outlines
void setMember(int i) { myPriMember_ = i; } // non-const Member Func.
void print() const { cout << myPriMember_ << ", " << myPubMember_ << endl; } // const Member Func.

T
const Objects };
Example
int main() { MyClass myObj(0, 1); // non-const object

P
const Member const MyClass myConstObj(5, 6); // const object
Functions // non-const object can invoke all member functions and update data members
Example
cout << myObj.getMember() << endl;

N
const Data myObj.setMember(2);
Members myObj.myPubMember_ = 3;
Example myObj.print();
Credit Card
// const object cannot allow any change
String Output
cout << myConstObj.getMember() << endl;
Date
// myConstObj.setMember(7); // Cannot invoke non-const member functions 0
Name
// myConstObj.myPubMember_ = 8; // Cannot update data member 2, 3
Address
myConstObj.print(); 5
CreditClass
} 5, 6
mutable
Members
Example
• Now myConstObj can invoke getMember() and print(), but cannot invoke setMember()
mutable Guidelines • Naturally myConstObj cannot update myPubMember
• myObj can invoke all of getMember(), print(), and setMember()
Module Summary
Programming in Modern C++ Partha Pratim Das M15.11
Constant Data Members

Module M15

L
Partha Pratim
Das

E
Objectives &
Outlines

T
const Objects
Example

P
const Member
Functions
Example

N
const Data
Members
Example
Credit Card
String
Date
Name
Address
Constant Data Members
CreditClass

mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.12
Constant Data members

Module M15
• Often we need part of an object, that is, one or more data members to be constant
(non-changeable after construction) while the rest of the data members should be

L
Partha Pratim
Das
changeable. For example:

E
Objectives &
Outlines ◦ For an Employee: employee ID and DoB should be non-changeable while

T
const Objects
Example
designation, address, salary etc. should be changeable
◦ For a Student: roll number and DoB should be non-changeable while year of

P
const Member
Functions
study, address, gpa etc. should be changeable
Example
◦ For a Credit Card1 : card number and name of holder should be

N
const Data
Members non-changeable while date of issue, date of expiry, address, cvv number
Example
Credit Card etc. should be changeable
String
Date • We do this by making the non-changeable data members as constant by putting the
Name
Address
const keyword before the declaration of the member in the class
CreditClass • A constant data member cannot be changed even in a non-constant object
mutable
Members
• A constant data member must be initialized on the initialization list
Example
mutable Guidelines 1 May not hold for a card that changes number on re-issue
Module Summary
Programming in Modern C++ Partha Pratim Das M15.13
Program 15.04: Constant Data Member
#include <iostream>
Module M15
using namespace std;
class MyClass { const int cPriMem_; /* const data member */ int priMem_; public:

L
Partha Pratim
Das const int cPubMem_; /* const data member */ int pubMem_;
MyClass(int cPri, int ncPri, int cPub, int ncPub) :

E
Objectives &
Outlines
cPriMem_(cPri), priMem_(ncPri), cPubMem_(cPub), pubMem_(ncPub) { }
int getcPri() { return cPriMem_; }

T
const Objects void setcPri(int i) { cPriMem_ = i; } // Error 1: Assignment to const data member
Example
int getPri() { return priMem_; }

P
const Member void setPri(int i) { priMem_ = i; }
Functions };
Example
int main() { MyClass myObj(1, 2, 3, 4);

N
const Data
Members cout << myObj.getcPri() << endl; myObj.setcPri(6);
Example cout << myObj.getPri() << endl; myObj.setPri(6);
Credit Card
String
cout << myObj.cPubMem_ << endl;
Date
myObj.cPubMem_ = 3; // Error 2: Assignment to const data member
Name
Address
CreditClass
cout << myObj.pubMem_ << endl; myObj.pubMem_ = 3;
}
mutable
Members
Example
• It is not allowed to make changes to constant data members in myObj
mutable Guidelines • Error 1: l-value specifies const object
• Error 2: ’myObj’ : you cannot assign to a variable that is const
Module Summary
Programming in Modern C++ Partha Pratim Das M15.14
Credit Card Example

Module M15
We now illustrate constant data members with a complete example of CreditCard class

L
Partha Pratim
Das with the following supporting classes:

E
Objectives &
Outlines
• String class
• Date class

T
const Objects
Example
• Name class

P
const Member
Functions
Example • Address class

N
const Data
Members
Example
Credit Card
String
Date
Name
Address
CreditClass

mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.15
Program 15.05: String Class: String.h
#include <iostream>
Module M15
#include <cstring>
#include <cstdlib>

L
Partha Pratim
Das using namespace std;

E
Objectives &
Outlines
class String { char *str_; size_t len_;
public:

T
const Objects String(const char *s) : str_(strdup(s)), len_(strlen(str_)) // Ctor
Example
{ cout << "String ctor: "; print(); cout << endl; }

P
const Member String(const String& s) : str_(strdup(s.str_)), len_(strlen(str_)) // CCtor
Functions { cout << "String cctor: "; print(); cout << endl; }
Example
String& operator=(const String& s) {

N
const Data if (this != &s) {
Members free(str_);
Example str_ = strdup(s.str_);
Credit Card
len_ = s.len_;
String
}
Date
return *this;
Name
Address
}
CreditClass
~String() { cout << "String dtor: "; print(); cout << endl; free(str_); } // Dtor
void print() const { cout << str_; }
mutable
Members
};
Example
mutable Guidelines • Copy Constructor and Copy Assignment Operator added
• print() made a constant member function
Module Summary
Programming in Modern C++ Partha Pratim Das M15.16
Program 15.05: Date Class: Date.h

Module M15 #include <iostream>


using namespace std;

L
Partha Pratim
Das
char monthNames[][4]={ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

E
Objectives & char dayNames[][10]={ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
Outlines
class Date {

T
const Objects enum Month { Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec };
Example enum Day { Mon, Tue, Wed, Thr, Fri, Sat, Sun };
typedef unsigned int UINT;

P
const Member
Functions UINT date_; Month month_; UINT year_;
Example public:

N
const Data
Date(UINT d, UINT m, UINT y) : date_(d), month_((Month)m), year_(y)
Members { cout << "Date ctor: "; print(); cout << endl; }
Example Date(const Date& d) : date_(d.date_), month_(d.month_), year_(d.year_)
Credit Card { cout << "Date cctor: "; print(); cout << endl; }
String Date& operator=(const Date& d) { date_ = d.date_; month_ = d.month_; year_ = d.year_; return *this; }
Date ~Date() { cout << "Date dtor: "; print(); cout << endl; }
Name
void print() const { cout << date_ << "/" << monthNames[month_ - 1] << "/" << year_; }
Address
bool validDate() const { /* Check validity */ return true; } // Not Implemented
CreditClass
Day day() const { /* Compute day from date using time.h */ return Mon; } // Not Implemented
mutable };
Members
Example
• Copy Constructor and Copy Assignment Operator added
mutable Guidelines
• print(), validDate(), and day() made constant member functions
Module Summary
Programming in Modern C++ Partha Pratim Das M15.17
Program 15.05: Name Class: Name.h

Module M15 #include <iostream>


using namespace std;

L
Partha Pratim
Das
#include "String.h"

E
Objectives &
Outlines
class Name { String firstName_, lastName_;

T
const Objects public:
Example Name(const char* fn, const char* ln) : firstName_(fn), lastName_(ln) // Uses Ctor of String class
{ cout << "Name ctor: "; print(); cout << endl; }

P
const Member
Functions Name(const Name& n) : firstName_(n.firstName_), lastName_(n.firstName_) // Uses CCtor of String class
Example { cout << "Name cctor: "; print(); cout << endl; }

N
const Data
Name& operator=(const Name& n) {
Members firstName_ = n.firstName_; // Uses operator=() of String class
Example lastName_ = n.lastName_; // Uses operator=() of String class
Credit Card return *this;
String }
Date ~Name() { cout << "Name dtor: "; print(); cout << endl; } // Uses Dtor of String class
Name
void print() const // Uses print() of String class
Address
{ firstName_.print(); cout << " "; lastName_.print(); }
CreditClass
};
mutable
Members • Copy Constructor and Copy Assignment Operator added
Example
• print() made a constant member function
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.18
Program 15.05: Address Class: Address.h

Module M15 #include <iostream>


using namespace std;

L
Partha Pratim
Das #include "String.h"

E
Objectives & class Address { unsigned int houseNo_; String street_, city_, pin_;
Outlines
public:

T
const Objects Address(unsigned int hn, const char* sn, const char* cn, const char* pin): // Uses Ctor of String class
Example houseNo_(hn), street_(sn), city_(cn), pin_(pin)
{ cout << "Address ctor: "; print(); cout << endl; }

P
const Member
Functions Address(const Address& a): // Uses CCtor of String class
Example houseNo_(a.houseNo_), street_(a.street_), city_(a.city_), pin_(a.pin_)

N
const Data
{ cout << "Address cctor: "; print(); cout << endl; }
Members Address& operator=(const Address& a) { // Uses operator=() of String class
Example houseNo_ = a.houseNo_; street_ = a.street_; city_ = a.city_; pin_ = a.pin_; return *this; }
Credit Card ~Address() { cout << "Address dtor: "; print(); cout << endl; } // Uses Dtor of String class
String void print() const { // Uses print() of String class
Date cout << houseNo_ << " "; street_.print(); cout << " ";
Name
city_.print(); cout << " "; pin_.print();
Address
}
CreditClass
};
mutable
Members • Copy Constructor and Copy Assignment Operator added
Example
• print() made a constant member function
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.19
Program 15.05: Credit Card Class: CreditCard.h
#include <iostream>
Module M15
using namespace std;
#include "Date.h"

L
Partha Pratim
Das #include "Name.h"
#include "Address.h"

E
Objectives &
Outlines
class CreditCard { typedef unsigned int UINT; char *cardNumber_;
Name holder_; Address addr_; Date issueDate_, expiryDate_; UINT cvv_;

T
const Objects public: CreditCard(const char* cNumber, const char* fn, const char* ln, unsigned int hn, const char* sn,
Example
const char* cn, const char* pin, UINT issueMonth, UINT issueYear, UINT expiryMonth, UINT expiryYear,

P
const Member UINT cvv): holder_(fn, ln), addr_(hn, sn, cn, pin), issueDate_(1, issueMonth, issueYear),
Functions expiryDate_(1, expiryMonth, expiryYear), cvv_(cvv) // Uses Ctor’s of Date, Name, Address
Example
{ cardNumber_ = new char[strlen(cNumber) + 1]; strcpy(cardNumber_, cNumber);

N
const Data cout << "CC ctor: "; print(); cout << endl; }
Members // Uses Dtor’s of Date, Name, Address
Example ~CreditCard() { cout << "CC dtor: "; print(); cout << endl; delete[] cardNumber_; }
Credit Card
void setHolder(const Name& h) { holder_ = h; } // Change holder name
String
void setAddress(const Address& a) { addr_ = a; } // Change address
Date
void setIssueDate(const Date& d) { issueDate_ = d; } // Change issue date
Name
Address
void setExpiryDate(const Date& d) { expiryDate_ = d; } // Change expiry date
CreditClass
void setCVV(UINT v) { cvv_ = v; } // Change cvv number
void print() const { cout<<cardNumber_<<" "; holder_.print(); cout<<" "; addr_.print();
mutable
Members
cout<<" "; issueDate_.print(); cout<<" "; expiryDate_.print(); cout<<" "; cout<<cvv_; }
Example
};
mutable Guidelines • Set methods added
• print() made a constant member function
Module Summary
Programming in Modern C++ Partha Pratim Das M15.20
Program 15.05: Credit Card Class Application
#include <iostream>
Module M15
using namespace std;
#include "CreditCard.h"

L
Partha Pratim
Das
int main() { CreditCard cc("5321711934640027", "Sherlock", "Holmes",

E
Objectives &
Outlines
221, "Baker Street", "London", "NW1 6XE", 7, 2014, 6, 2016, 811);
cout << endl; cc.print(); cout << endl << endl;;

T
const Objects
Example
cc.setHolder(Name("David", "Cameron"));

P
const Member cc.setAddress(Address(10, "Downing Street", "London", "SW1A 2AA"));
Functions cc.setIssueDate(Date(1, 7, 2017));
Example
cc.setExpiryDate(Date(1, 6, 2019));

N
const Data cc.setCVV(127);
Members cout << endl; cc.print(); cout << endl << endl;;
Example }
Credit Card
String
// Construction of Data Members & Object
Date
5321711934640027 Sherlock Holmes 221 Baker Street London NW1 6XE 1/Jul/2014 1/Jun/2016 811
Name
Address // Construction & Destruction of temporary objects
CreditClass 5321711934640027 David Cameron 10 Downing Street London SW1A 2AA 1/Jul/2017 1/Jun/2019 127
mutable
Members // Destruction of Data Members & Object
Example
mutable Guidelines • We could change address, issue date, expiry date, and cvv. This is fine
• We could change the name of the holder! This should not be allowed
Module Summary
Programming in Modern C++ Partha Pratim Das M15.21
Program 15.06: Credit Card Class: Constant data members

Module M15
// Include <iostream>, "String.h", "Date.h", "Name.h", "Address.h"
using namespace std;

L
Partha Pratim
Das
class CreditCard { typedef unsigned int UINT;

E
Objectives & char *cardNumber_;
Outlines
const Name holder_; // Holder name cannot be changed after construction

T
const Objects Address addr_; Date issueDate_, expiryDate_; UINT cvv_;
Example public: CreditCard(...) : ... { ... } ~CreditCard() { ... }

P
const Member
Functions void setHolder(const Name& h) { holder_ = h; } // Change holder name
Example // error C2678: binary ’=’ : no operator found which takes a left-hand operand

N
const Data // of type ’const Name’ (or there is no acceptable conversion)
Members
Example void setAddress(const Address& a) { addr_ = a; } // Change address
Credit Card void setIssueDate(const Date& d) { issueDate_ = d; } // Change issue date
String void setExpiryDate(const Date& d) { expiryDate_ = d; } // Change expiry date
Date
void setCVV(UINT v) { cvv_ = v; } // Change cvv number
Name
Address
void print() { ... }
CreditClass
};
mutable
Members
• We prefix Name holder with const. Now the holder name cannot be changed after construction
Example
• In setHolder(), we get a compilation error for holder = h; in an attempt to change holder
mutable Guidelines
• With const prefix Name holder becomes constant – unchangeable
Module Summary
Programming in Modern C++ Partha Pratim Das M15.22
Program 15.06: Credit Card Class: Clean

Module M15
// Include <iostream>, "String.h", "Date.h", "Name.h", "Address.h"
using namespace std;

L
Partha Pratim
Das
class CreditCard { typedef unsigned int UINT;

E
Objectives & char *cardNumber_;
Outlines
const Name holder_; // Holder name cannot be changed after construction

T
const Objects Address addr_;
Example Date issueDate_, expiryDate_; UINT cvv_;
public:

P
const Member
Functions CreditCard(...) : ... { ... }
Example ~CreditCard() { ... }

N
const Data
Members void setAddress(const Address& a) addr_ = a; // Change address
Example void setIssueDate(const Date& d) issueDate_ = d; // Change issue date
Credit Card void setExpiryDate(const Date& d) expiryDate_ = d; // Change expiry date
String void setCVV(UINT v) cvv_ = v; // Change cvv number
Date
Name
void print() { ... }
Address
};
CreditClass

mutable • Method setHolder() removed


Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.23
Program 15.06: Credit Card Class Application: Revised
#include <iostream>
Module M15
using namespace std;
#include "CreditCard.h"

L
Partha Pratim
Das int main() {
CreditCard cc("5321711934640027", "Sherlock", "Holmes",

E
Objectives &
Outlines
221, "Baker Street", "London", "NW1 6XE", 7, 2014, 6, 2016, 811);
cout << endl; cc.print(); cout << endl << endl;;

T
const Objects
Example
// cc.setHolder(Name("David", "Cameron"));

P
const Member cc.setAddress(Address(10, "Downing Street", "London", "SW1A 2AA"));
Functions cc.setIssueDate(Date(1, 7, 2017));
Example
cc.setExpiryDate(Date(1, 6, 2019));

N
const Data cc.setCVV(127);
Members cout << endl; cc.print(); cout << endl << endl;;
Example }
Credit Card
String
// Construction of Data Members & Object
Date
5321711934640027 Sherlock Holmes 221 Baker Street London NW1 6XE 1/Jul/2014 1/Jun/2016 811
Name
Address // Construction & Destruction of temporary objects
CreditClass 5321711934640027 Sherlock Holmes 10 Downing Street London SW1A 2AA 1/Jul/2017 1/Jun/2019 127
mutable
Members // Destruction of Data Members & Object
Example
mutable Guidelines • Now holder cannot be changed. So we are safe
• However, it is still possible to replace or edit the card number. This, too, should be disallowed
Module Summary
Programming in Modern C++ Partha Pratim Das M15.24
Program 15.07: Credit Card Class: cardNumber Issue

Module M15
// Include <iostream>, "String.h", "Date.h", "Name.h", "Address.h"
using namespace std;

L
Partha Pratim
Das
class CreditCard { typedef unsigned int UINT;

E
Objectives & char *cardNumber_; // Card number is editable as well as replaceable
Outlines
const Name holder_; // Holder name cannot be changed after construction

T
const Objects Address addr_;
Example Date issueDate_, expiryDate_; UINT cvv_;
public:

P
const Member
Functions CreditCard(...) : ... { ... }
Example ~CreditCard() { ... }

N
const Data
Members void setAddress(const Address& a) { addr_ = a; } // Change address
Example void setIssueDate(const Date& d) { issueDate_ = d; } // Change issue date
Credit Card void setExpiryDate(const Date& d) { expiryDate_ = d; } // Change expiry date
String void setCVV(UINT v) { cvv_ = v; } // Change cvv number
Date
Name
void print() { ... }
Address
};
CreditClass

mutable • It is still possible to replace or edit the card number


Members
• To make the cardNumber non-replaceable, we need to make this constant pointer
Example
• Further, to make it non-editable we need to make cardNumber point to a constant string
mutable Guidelines
• Hence, we change char *cardNumber to const char * const cardNumber
Module Summary
Programming in Modern C++ Partha Pratim Das M15.25
Program 15.07: Credit Card Class: cardNumber Issue

Module M15
// Include <iostream>, "String.h", "Date.h", "Name.h", "Address.h"
using namespace std;

L
Partha Pratim
Das class CreditCard {
typedef unsigned int UINT;

E
Objectives & const char * const cardNumber_; // Card number cannot be changed after construction
Outlines
const Name holder_; // Holder name cannot be changed after construction

T
const Objects Address addr_; Date issueDate_, expiryDate_; UINT cvv_;
Example public: CreditCard(const char* cNumber, const char* fn, const char* ln,
unsigned int hn, const char* sn, const char* cn, const char* pin,

P
const Member
Functions UINT issueMonth, UINT issueYear, UINT expiryMonth, UINT expiryYear, UINT cvv) :
Example holder_(fn, ln), addr_(hn, sn, cn, pin), issueDate_(1, issueMonth, issueYear),

N
const Data expiryDate_(1, expiryMonth, expiryYear), cvv_(cvv) {
Members cardNumber_ = new char[strlen(cNumber) + 1]; // ERROR: No assignment to const pointer
Example strcpy(cardNumber_, cNumber); // ERROR: No copy to const C-string
Credit Card cout << "CC ctor: "; print(); cout << endl;
String }
Date
~CreditCard() { cout << "CC dtor: "; print(); cout << endl; delete[] cardNumber_; }
Name
Address
// Set methods and print method skipped ...
CreditClass
};
mutable • cardNumber is now a constant pointer to a constant string
Members
• With this the allocation for the C-string fails in the body as constant pointer cannot be assigned
Example
• Further, copy of C-string (strcpy()) fails as copy of constant C-string is not allowed
mutable Guidelines
• We need to move these codes to the initialization list
Module Summary
Programming in Modern C++ Partha Pratim Das M15.26
Program 15.07: Credit Card Class: cardNumber Issue: Resolved

Module M15
// Include <iostream>, "String.h", "Date.h", "Name.h", "Address.h"
using namespace std;

L
Partha Pratim
Das class CreditCard { typedef unsigned int UINT;
const char * const cardNumber_; // Card number cannot be changed after construction

E
Objectives & const Name holder_; // Holder name cannot be changed after construction
Outlines
Address addr_; Date issueDate_, expiryDate_; UINT cvv_;

T
const Objects public: CreditCard(const char* cNumber, const char* fn, const char* ln,
Example unsigned int hn, const char* sn, const char* cn, const char* pin,
UINT issueMonth, UINT issueYear, UINT expiryMonth, UINT expiryYear, UINT cvv) :

P
const Member
Functions cardNumber_(strcpy(new char[strlen(cNumber)+1], cNumber)),
Example holder_(fn, ln), addr_(hn, sn, cn, pin), issueDate_(1, issueMonth, issueYear),

N
const Data expiryDate_(1, expiryMonth, expiryYear), cvv_(cvv)
Members { cout << "CC ctor: "; print(); cout << endl; }
Example ~CreditCard() { cout << "CC dtor: "; print(); cout << endl; delete[] cardNumber_; }
Credit Card void setAddress(const Address& a) { addr_ = a; } // Change address
String void setIssueDate(const Date& d) { issueDate_ = d; } // Change issue date
Date
void setExpiryDate(const Date& d) { expiryDate_ = d; } // Change expiry date
Name
void setCVV(UINT v) { cvv_ = v; } // Change cvv number
Address
void print() const { cout<<cardNumber_<<" "; holder_.print(); cout<<" "; addr_.print();
CreditClass
cout<<" "; issueDate_.print(); cout<<" "; expiryDate_.print(); cout<<" "; cout<<cvv_; }
mutable };
Members
Example
• Note the initialization of cardNumber in initialization list
mutable Guidelines
• All constant data members must be initialized in initialization list
Module Summary
Programming in Modern C++ Partha Pratim Das M15.27
mutable Members

Module M15

L
Partha Pratim
Das

E
Objectives &
Outlines

T
const Objects
Example

P
const Member
Functions
Example

N
const Data
Members
Example
Credit Card
String
Date
Name
Address
mutable Members
CreditClass

mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.28
mutable Data Members

Module M15

• While a constant data member is not changeable even in a non-constant object, a

L
Partha Pratim
Das
mutable data member is changeable in a constant object

E
Objectives &
Outlines • mutable is provided to model Logical (Semantic) const-ness against the default
Bit-wise (Syntactic) const-ness of C++

T
const Objects
Example
• Note that:

P
const Member
Functions
Example
◦ mutable is applicable only to data members and not to variables

N
const Data ◦ Reference data members cannot be declared mutable
Members
Example
◦ Static data members cannot be declared mutable
Credit Card ◦ const data members cannot be declared mutable
String
Date
• If a data member is declared mutable, then it is legal to assign a value to it from a
Name
Address const member function
CreditClass

mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.29
Program 15.08: mutable Data Members

Module M15 #include <iostream>


using namespace std;

L
Partha Pratim
Das
class MyClass {
int mem_;

E
Objectives & mutable int mutableMem_;
Outlines public:
MyClass(int m, int mm) : mem_(m), mutableMem_(mm) { }

T
const Objects
Example int getMem() const { return mem_; }
void setMem(int i) { mem_ = i; }

P
const Member
Functions
int getMutableMem() const { return mutableMem_; }
Example
void setMutableMem(int i) const { mutableMem_ = i; } // Okay to change mutable

N
};
const Data
Members
int main() { const MyClass myConstObj(1, 2);
Example
Credit Card cout << myConstObj.getMem() << endl;
String // myConstObj.setMem(3); // Error to invoke
Date
Name cout << myConstObj.getMutableMem() << endl;
Address myConstObj.setMutableMem(4);
CreditClass }
mutable
Members • setMutableMem() is a constant member function so that constant myConstObj can invoke it
Example • setMutableMem() can still set mutableMem because mutableMem is mutable
mutable Guidelines • In contrast, myConstObj cannot invoke setMem() and hence mem cannot be changed
Module Summary
Programming in Modern C++ Partha Pratim Das M15.30
Logical vis-a-vis Bit-wise Const-ness

Module M15

• const in C++, models bit-wise constant. Once an object is declared const, no part

L
Partha Pratim
Das
(actually, no bit) of it can be changed after construction (and initialization)

E
Objectives &
Outlines • However, while programming we often need an object to be logically constant. That is,
the concept represented by the object should be constant; but if its representation need

T
const Objects
Example
more data members for computation and modeling, these have no reason to be

P
const Member
Functions constant.
Example
• mutable allows such surrogate data members to be changeable in a (bit-wise) constant

N
const Data
Members
Example
object to model logically const objects
Credit Card
String
• To use mutable we shall look for:
Date
◦ A logically constant concept
Name
Address ◦ A need for data members outside the representation of the concept; but are needed
CreditClass
for computation
mutable
Members
Example
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.31
Program 15.09: When to use mutable Data Members?

Module M15 • Typically, when a class represents a constant concept, and


• It computes a value first time and caches the result for future use

L
Partha Pratim
Das // Source: http://www.highprogrammer.com/alan/rants/mutable.html
#include <iostream>

E
Objectives &
Outlines
using namespace std;
class MathObject { // Constant concept of PI

T
const Objects
mutable bool piCached_; // Needed for computation
Example
mutable double pi_; // Needed for computation

P
const Member public:
Functions MathObject() : piCached_(false) { } // Not available at construction
Example
double pi() const { // Can access PI only through this method

N
const Data if (!piCached_) { // An insanely slow way to calculate pi
Members pi_ = 4;
Example
for (long step = 3; step < 1000000000; step += 4) {
Credit Card
pi_ += ((-4.0 / (double)step) + (4.0 / ((double)step + 2)));
String
}
Date
Name
piCached_ = true; // Now computed and cached
Address
}
CreditClass return pi_;
}
mutable
Members };
Example int main() { const MathObject mo; cout << mo.pi() << endl; /* Access PI */ }
mutable Guidelines
• Here a MathObject is logically constant; but we use mutable members for computation
Module Summary
Programming in Modern C++ Partha Pratim Das M15.32
Program 15.10: When not to use mutable Data Members?

Module M15 • mutable should be rarely used – only when it is really needed. A bad example follows:
Improper Design (mutable) Proper Design (const)

L
Partha Pratim
Das
class Employee { string _name, _id; class Employee { const string _name, _id;
mutable double _salary; double _salary;

E
Objectives &
Outlines public: Employee(string name = "No Name", public: Employee(string name = "No Name",
string id = "000-00-0000", string id = "000-00-0000",

T
const Objects
double salary = 0): _name(name), _id(id) double salary = 0): _name(name), _id(id)
Example
{ _salary = salary; } { _salary = salary; }

P
const Member string getName() const; string getName() const;
Functions
void setName(string name); // void setName(string name); // _name is const
Example
string getid() const; string getid() const;

N
const Data void setid(string id); // void setid(string id); // _id is const
Members
double getSalary() const; double getSalary() const;
Example
void setSalary(double salary); void setSalary(double salary);
Credit Card
String
void promote(double salary) const void promote(double salary)
Date
{ _salary = salary; } { _salary = salary; }
Name
}; };
Address --- ---
CreditClass const Employee john("JOHN","007",5000.0); Employee john("JOHN","007",5000.0);
mutable
// ... // ...
Members john.promote(20000.0); john.promote(20000.0);
Example
mutable Guidelines • Employee is not logically constant. If it is, then salary should also be const
• Design on right makes that explicit
Module Summary
Programming in Modern C++ Partha Pratim Das M15.33
Module Summary

Module M15

• Studied const-ness in C++

L
Partha Pratim
Das
• In C++, there are three forms of const-ness

E
Objectives &
Outlines ◦ Constant Objects

T
const Objects
Example
. No change is allowed after construction
. Cannot invoke normal member functions

P
const Member
Functions
Example ◦ Constant Member Functions

N
const Data
Members
. Can be invoked by constant (as well as non-constant) objects
Example . Cannot make changes to the object
Credit Card
String ◦ Constant Data Members
Date
Name . No change is allowed after construction
Address
CreditClass
. Must be initialized in the initialization list
mutable • Further, learnt how to model logical const-ness over bit-wise const-ness by proper use
Members
Example of mutable members
mutable Guidelines

Module Summary
Programming in Modern C++ Partha Pratim Das M15.34
Tutorial T03

L
Partha Pratim
Das
Programming in Modern C++

E
Tutorial Recap

Objectives & Tutorial T03: How to build a C/C++ program?: Part 3: make Utility

T
Outline

make Utility

P
Example Build
Why make?
Partha Pratim Das

N
Anatomy of a
makefile
Simple makefile
Variables Department of Computer Science and Engineering
Dependency Indian Institute of Technology, Kharagpur
Source Organization

make Command ppd@cse.iitkgp.ac.in


Options and Features
Capabilities and
Derivatives
All url’s in this module have been accessed in September, 2021 and found to be functional
Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.1


Tutorial Recap

Tutorial T03

• Understood the overall build process for a C/C++ project with specific reference to the

L
Partha Pratim
Das
build pipeline of GCC

E
Tutorial Recap
• Understood the differences and relationships between source and header files
Objectives &

T
Outline
• Understood how CPP can be harnessed to manage code during build
make Utility
• Understood the management of C/C++ dialects and C/C++ Standard Libraries

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives

Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.2


Tutorial Objective

Tutorial T03

• Building a software project is a laborious, error-prone, and time consuming process. So

L
Partha Pratim
Das
it calls for automation by scripting

E
Tutorial Recap
• make, primarily from GNU, is the most popular free and open source
Objectives &
dependency-tracking builder tool that all software developers need to know

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives

Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.3


Tutorial Outline

Tutorial T03
1 Tutorial Recap

L
Partha Pratim
Das
2 make Utility

E
Tutorial Recap

Objectives &
Example Build

T
Outline Why make?
make Utility

P
Example Build
Why make?
3 Anatomy of a makefile
Simple makefile

N
Anatomy of a
makefile
Simple and Recursive Variables
Simple makefile
Variables Dependency
Dependency
Source Organization
Source Organization
make Command
Options and Features
4 make Command
Capabilities and
Derivatives
Options and Features
Tutorial Summary Capabilities and Derivatives
5 Tutorial Summary
Programming in Modern C++ Partha Pratim Das T03.4
make Utility

Tutorial T03

L
Partha Pratim
Das

E
Tutorial Recap

Objectives &

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
make Utility
Capabilities and
Derivatives Source: Accessed 15-Sep-21
GNU make Manual
Tutorial Summary GNU Make
A Simple Makefile Tutorial

Programming in Modern C++ Partha Pratim Das T03.5


make Utility: Example Build

Tutorial T03 • Consider a tiny project comprising three files – main.c, hello.c, and hello.h in a folder
main.c hello.c hello.h

L
Partha Pratim
Das

E
Tutorial Recap #include "hello.h" #include <stdio.h> // example include file
Objectives & #include "hello.h" #ifndef __HEADER_H

T
Outline int main() { #define __HEADER_H
make Utility // call a function in void myHello(void) {

P
Example Build
// another file printf("Hello World!\n"); void myHello(void);
Why make?
myHello(); return;

N
Anatomy of a
makefile return 0; } #endif // __HEADER_H
Simple makefile }
Variables
Dependency
Source Organization • We build this by executing the command in the current folder (-I.):
make Command gcc -o hello hello.c main.c -I. // Generates hello.o & main.o and removes at the end
Options and Features
Capabilities and
which actually expands to:
Derivatives
gcc -c hello.c -I. // Compile and Generate hello.o
Tutorial Summary gcc -c main.c -I. // Compile and Generate main.o
gcc -o hello hello.o main.o -I. // Link and Generate hello
rm -f hello.o main.o // Is it really necessary? . hello.o & main.o may be retained
Programming in Modern C++ Partha Pratim Das T03.6
Why we need make Utility?

Tutorial T03 • This manual process of build would be difficult in any practical software project due to:
◦ [Volume] Projects have hundreds of folders, source and header files. They need hundreds

L
Partha Pratim
Das
of commands. It is time-taking to type the commands and is error-prone

E
Tutorial Recap ◦ [Workload] Build needs to be repeated several times a day with code changes in some file/s
Objectives & ◦ [Depenency] Often with the change in one file, all translation units do not need to be

T
Outline

make Utility
re-compiled (assuming that we do not remove .o files). For example:
. If we change only hello.c, we do not need to execute

P
Example Build
Why make?
gcc -c main.c -I. // main.o is already correct

N
Anatomy of a
makefile . If we change only main.c, we do not need to execute
Simple makefile
gcc -c hello.c -I. // hello.o is already correct
Variables
Dependency . However, if we change hello.h, we need to execute all
Source Organization

make Command
There are dependencies in build that can be exploited to optimize the build effort
Options and Features ◦ [Diversity] Finally, we may need to use different build tools for different files, different build
Capabilities and
Derivatives flags, different folder structure etc.
Tutorial Summary • This calls for automation by scripting. GNU Make is a tool which controls the generation of
executables and other non-source files of a program from the program’s source files

Programming in Modern C++ Partha Pratim Das T03.7


Why we need make Utility?: What happened in Bell Labs

Tutorial T03

L
Partha Pratim
Das

E
Tutorial Recap

Objectives &

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives

Tutorial Summary

Stuart Feldman created make in April 1976 at Bell Labs


Makefile Martial Arts - Chapter 1. The morning of creation
Programming in Modern C++ Partha Pratim Das T03.8
Anatomy of a makefile

Tutorial T03

L
Partha Pratim
Das

E
Tutorial Recap

Objectives &

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile Make (software), Wikipedia
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives
Anatomy of a makefile
Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.9


makefile: Anatomy

Tutorial T03 • A simple make file would be like (makefile 1.txt):


hello: hello.c main.c

L
Partha Pratim
Das
gcc -o hello hello.c main.c -I.

E
Tutorial Recap Write these lines in a text file named makefile or Makefile and run make command and it
Objectives & will execute the command:

T
Outline
$ make
make Utility
gcc -o hello hello.c main.c -I.

P
Example Build
Why make?
• Make file comprises a number of Rules. Every rule has a target to build, a colon separator (:),

N
Anatomy of a
makefile zero or more files on which the target depends on and the commands to build on the next line
Simple makefile hello: hello.c main.c # Rule 1
Variables
Dependency
gcc -o hello hello.c main.c -I.
Source Organization • Note:
make Command
Options and Features
◦ There must be a tab at the beginning of any command. Spaces will not work!
Capabilities and
Derivatives
◦ If any of the file in the dependency (hello.c or main.c) change since the last time make was
Tutorial Summary
done (target hello was built), the rule will fire and the command (gcc) will execute. This
is decided by the last update timestamp of the files
◦ Hash (#) starts a comment that continues till the end of the line
Programming in Modern C++ Partha Pratim Das T03.10
makefile: Anatomy

Tutorial T03

L
Partha Pratim
Das

E
Tutorial Recap

Objectives &

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives

Tutorial Summary

How to Write a Makefile with Ease


Programming in Modern C++ Partha Pratim Das T03.11
makefile: Architecture

Tutorial T03

L
Partha Pratim
Das

E
Tutorial Recap

Objectives &

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives

Tutorial Summary

Makefile Martial Arts - Chapter 1. The morning of creation


Programming in Modern C++ Partha Pratim Das T03.12
makefile: Simple and Recursive Variables

Tutorial T03 • We can make the make file smarter (makefile 2.txt) using variables:
# CC is a simple variable, gcc is its value

L
Partha Pratim
Das CC := gcc
# CFLAGS is a recursive variable, -I. is its value

E
Tutorial Recap CFLAGS = -I.
Objectives &

T
Outline hello: hello.c main.c # Rule 1
$(CC) -o hello hello.c main.c $CFLAGS
make Utility
# $(CC) is value gcc of CC, $CFLAGS is value -I. of CFLAGS, Variables can be expanded by $(.) or ${.}

P
Example Build
Why make? • If there are several commands, to change gcc to g++, we just need to change one line CC=g++.
• There are two types of variables in make (Chapter 3. Variables and Macros, O’Reilly)

N
Anatomy of a
makefile
Simple makefile ◦ Simply expanded variables (defined by := operator) and evaluated as soon as encountered
Variables
Dependency
◦ Recursively expanded variables (by =) and lazily evaluated, may be defined after use
Source Organization

make Command Simply Expanded Recurively Expanded


Options and Features MAKE_DEPEND := $(CC) -M MAKE_DEPEND = $(CC) -M
Capabilities and ... ...
Derivatives
# Some time later # Some time later
Tutorial Summary CC = gcc CC = gcc
$(MAKE DEPEND)$ expands to:

<space>-M gcc -M
Programming in Modern C++ Partha Pratim Das T03.13
makefile: Dependency

Tutorial T03
• We are still missing the dependency on the include (header) files. If hello.h changes,
the above Rule 1 will not detect the need for a re-build. So we improve further

L
Partha Pratim
Das
(makefile 3.txt):

E
Tutorial Recap
CC=gcc
Objectives &
CFLAGS=-I.

T
Outline

make Utility
#Set of header files on which .c depends
DEPS = hello.h

P
Example Build
Why make?
# Rule 1: Applies to all files ending in the .o suffix

N
Anatomy of a
makefile
# The .o file depends upon the .c version of the file and the .h files in the DEPS macro
Simple makefile
Variables
# To generate the .o file, make needs to compile the .c file using the CC macro
Dependency # The -c flag says to generate the object file
Source Organization # The -o $@ says to put the output of the compilation in the file named on the LHS of :
make Command # The $< is the first item in the dependencies list
Options and Features
%.o: %.c $(DEPS)
Capabilities and
Derivatives $(CC) -c -o $@ $< $(CFLAGS)
Tutorial Summary
hello: hello.o main.o # Rule 2: Link .o files
$(CC) -o hello hello.o main.o -I.
Programming in Modern C++ Partha Pratim Das T03.14
makefile: Dependency

Tutorial T03
• We can further simplify on the object files (makefile 4.txt):

L
Partha Pratim CC=gcc
Das
CFLAGS=-I.

E
Tutorial Recap DEPS = hello.h
Objectives & #Set of object files on which executable depends

T
Outline OBJ = hello.o main.o
make Utility

P
Example Build
# Rule 1: Applies to all files ending in the .o suffix
Why make?
%.o: %.c $(DEPS)

N
Anatomy of a
makefile $(CC) -c -o $@ $< $(CFLAGS)
Simple makefile
Variables # Rule 2: Linking step, applies to the executable depending on the file in OBJ macro
Dependency
Source Organization
# The -o $@ says to put the output of the linking in the file named on the LHS of :
# The $^ is the files named on the RHS of :
make Command
Options and Features
hello: $(OBJ)
Capabilities and $(CC) -o $@ $^ $(CFLAGS)
Derivatives

Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.15


makefile: Code Organization

Tutorial T03
• Finally, let us introduce a source organization that is typical of a large project where
under a project Home folder, we have the following folders:

L
Partha Pratim
Das

◦ Home: The make file and the following folders:

E
Tutorial Recap

Objectives & . bin: The executable of the project. For example hello / hello.exe

T
Outline
. inc: The include / header (.h) files of the project. For example hello.h
make Utility
. lib: The local library files (.a) of the project

P
Example Build
Why make?
. obj: The object files (.o) of the project. For example hello.o & main.o

N
Anatomy of a
makefile . src: The source files (.c/.cpp) of the project. For example hello.c & main.c
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives

Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.16


makefile: Code Tree

Tutorial T03
Home // Project Home

L
Partha Pratim
Das
|
---- bin // Application binary

E
Tutorial Recap | |
| ---- hello.exe
Objectives &
|

T
Outline
---- inc // Headers files to be included in application
make Utility | |

P
Example Build
| ---- hello.h
Why make?
|

N
Anatomy of a ---- lib // Library files to be linked to application. Check Tutorial Static and Dynamic Library
makefile
|
Simple makefile
---- obj // Object files
Variables
Dependency
| |
Source Organization
| ---- hello.o
| ---- main.o
make Command
|
Options and Features
---- src // Source files
Capabilities and
Derivatives |
| ---- hello.c
Tutorial Summary
| ---- main.c
|
---- makefile // Makefile
Programming in Modern C++ Partha Pratim Das T03.17
makefile: Code Organization

Tutorial T03 • To handle this hierarchy, we modify as (makefile 5.txt):


CC = gcc

L
Partha Pratim
Das
# Folders
BDIR = bin

E
Tutorial Recap IDIR = inc
LDIR = lib
Objectives &
ODIR = obj

T
Outline
SDIR = src
make Utility # Flags

P
Example Build
CFLAGS = -I$(IDIR)
Why make?
# Macros

N
Anatomy of a _DEPS = hello.h # Add header files here
makefile
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
Simple makefile
_SRC = hello.c main.c # Add source files here
Variables
Dependency
SRC = $(patsubst %,$(SDIR)/%,$(_SRC))
Source Organization
_OBJ = hello.o main.o # Add source files here
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
make Command
# Rule 1: Object files
Options and Features
$(ODIR)/%.o: $(SDIR)/%.c $(DEPS); $(CC) -c -o $@ $< $(CFLAGS) -I.
Capabilities and
Derivatives #Rule 2: Binary File Set binary file here
$(BDIR)/hello: $(OBJ); $(CC) -o $@ $^ $(CFLAGS)
Tutorial Summary
# Rule 3: Remove generated files. .PHONY rule keeps make from doing something with a file named clean
.PHONY: clean
clean: ; del $(ODIR)\*.o $(BDIR)\*.exe
# rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
Programming in Modern C++ Partha Pratim Das T03.18
make Command

Tutorial T03

L
Partha Pratim
Das

E
Tutorial Recap

Objectives &

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
make Command
Capabilities and
Derivatives

Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.19


make Command: Options and Features

Tutorial T03 • The format of make command is:


make [ -f makefile ] [ options ] ... [ targets ] ...

L
Partha Pratim
Das make executes commands in the makefile to update one or more target names
◦ With no -f, make looks for makefile, and Makefile. To use other files do:

E
Tutorial Recap

Objectives &
$ make -f makefile_1.txt // Using makefile_1.txt

T
Outline gcc -o hello hello.c main.c -I.
make Utility ◦ make updates a target if its prerequisite files are dated. Starting empty obj & bin folders:

P
Example Build $ make -f makefile_5.txt obj/hello.o // Build hello.o, place in obj
Why make?
gcc -c -o obj/hello.o src/hello.c -Iinc -I.

N
Anatomy of a
makefile $ make -f makefile_5.txt obj/main.o // Build main.o, place in obj
Simple makefile gcc -c -o obj/main.o src/main.c -Iinc -I.
Variables
Dependency
$ make -f makefile_5.txt bin/hello // Build hello.exe linking .o files and place in bin
Source Organization
gcc -o bin/hello obj/hello.o obj/main.o -Iinc
make Command
Options and Features
$ make -f makefile_5.txt clean // Remove non-text files generated - obj/*.o & bin/*.exe
Capabilities and
Derivatives
del obj\*.o bin\*.exe
Tutorial Summary
$ make -f makefile_5.txt // By default targets bin/hello and builds all
gcc -c -o obj/hello.o src/hello.c -Iinc -I.
gcc -c -o obj/main.o src/main.c -Iinc -I.
gcc -o bin/hello obj/hello.o obj/main.o -Iinc
Programming in Modern C++ Partha Pratim Das T03.20
make Command: Options and Features

Tutorial T03 • More make options / features:


◦ To change to directory dir before reading the makefiles, use -C dir

L
Partha Pratim
Das
◦ To print debugging information in addition to normal processing, use -d

E
Tutorial Recap ◦ To specify a directory dir to search for included makefiles, use -I dir
Objectives & ◦ To print the version of the make program, use -v. We are using

T
Outline
GNU Make 3.81
make Utility
Copyright (C) 2006 Free Software Foundation, Inc.

P
Example Build
This is free software; see the source for copying conditions.
Why make?
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

N
Anatomy of a
makefile
This program built for i386-pc-mingw32
Simple makefile
Variables ◦ make can be recursive - one make file may include a command to make another
Dependency
Source Organization
◦ Multiline: The backslash (“\”) character gives us the ability to use multiple lines when the
make Command commands are too long
Options and Features some_file:
Capabilities and echo This line is too long, so \
Derivatives
it is broken up into multiple lines
Tutorial Summary
◦ Comments: Lines starting with # are used for comments
◦ Macros: Besides simple and recursive variables, make also supports macros
Programming in Modern C++ Partha Pratim Das T03.21
make Utility: Capabilities and Derivatives

Tutorial T03
• make was created by Stuart Feldman in April 1976 at Bell Labs and included in Unix since
PWB/UNIX 1.0. He received the 2003 ACM Software System Award for make

L
Partha Pratim
Das
• make is one of the most popular build utilities having the following major Capabilities:

E
Tutorial Recap
◦ make enables the end user to build and install a package without knowing the details of
Objectives &
how that is done (it is in the makefile supplied by the user)

T
Outline

make Utility ◦ make figures out automatically which files it needs to update, based on which source files

P
Example Build
have changed and automatically determines the proper order for updating files
Why make?
◦ make is not limited to any particular language - C, C++, Java, and so on.

N
Anatomy of a
makefile ◦ make is not limited to building a package - can control installation/uninstallation etc.
Simple makefile
Variables • make has several Derivative and is available on all OS platforms:
Dependency
Source Organization
◦ GNU Make (all types of Unix): Used to build many software systems, including:
make Command . GCC, the Linux kernel, Apache OpenOffice, LibreOffice, and Mozilla Firefox
Options and Features
Capabilities and
◦ Make for Windows, GnuWin32 (We are using here)
Derivatives
◦ Microsoft nmake, a command-line tool, part of Visual Studio
Tutorial Summary
◦ Kati is Google’s replacement of GNU Make, used in Android OS builds. It translates the
makefile into Ninja (used for Chrome) for faster incremental builds
All links Accessed on 21-Sep-21
Programming in Modern C++ Partha Pratim Das T03.22
Tutorial Summary

Tutorial T03

• Learnt make, the most popular free and open source dependency-tracking builder tool,

L
Partha Pratim
Das
with its anatomy, architecture and options through a series of examples

E
Tutorial Recap

Objectives &

T
Outline

make Utility

P
Example Build
Why make?

N
Anatomy of a
makefile
Simple makefile
Variables
Dependency
Source Organization

make Command
Options and Features
Capabilities and
Derivatives

Tutorial Summary

Programming in Modern C++ Partha Pratim Das T03.23

You might also like