Object-Oriented
Programming
WEEK 04 Abeeha Sattar
Destructors
Destructor is a member function which destructs or deletes an object.
It is called automatically when:
Object goes out of scope
Function ends
Program ends
Block with local object ends
delete is called
How destructors are different from
a normal member function?
Like Constructors, they share the same name as the class
They do not return anything
They do not accept any arguments
Unlike constructors, there can only be one destructor.
Most importantly, they are preceded by a ‘tilde’ symbol. ~
When to write a user-defined
destructor?
If we do not write our own destructor in class, compiler creates a default destructor for
us.
The default destructor works fine unless we have dynamically allocated memory or
pointer in class.
In this case we need to write our own destructor and then deallocate the memory pointed to
by the pointed by using the delete keyword
Destructor for our class…
class BankAccount { interest_rate = _interest_rate;
private: }
double balance; BankAccount(const BankAccount &bankAccount) {
double interest_rate; balance = [Link];
interest_rate =
bankAccount.interest_rate;
public:
}
BankAccount() { //default constructor
void showDetails() {
balance = 0.01;
cout << "Bal: " << balance << "\nIR: " <<
interest_rate = 0.01;
} interest_rate;
BankAccount(double _balance) { }
balance = _balance; ~BankAccount() {
} cout << "Destructor is called";
BankAccount(double _balance, double }
_interest_rate) {
};
Shallow Copy | Deep Copy
Shallow Copy:
When you only copy values from one thing to another.
Compiler generated copy constructors only perform shallow copy!
Example – Without Custom Copy
Constructor:
class BankAccount { void setBalance(double _balance) {
private: balance = _balance;
double balance; }
double interest_rate; void setinterestRate(double _interest_rate) {
Pointer
double* ID; interest_rate = _interest_rate;
member
public: }
BankAccount() { //default constructor void showDetails() {
balance = 0.01; cout << "ID: " << *ID << "\nBal: " <<
Allocating balance << "\nIR: " <<
interest_rate = 0.01;
memory and interest_rate;
ID = new double; setting a value }
*ID = 10.01;
~BankAccount() {
}
cout << "Destructor is called\n";
void setID(double _ID) {
delete ID; Don’t forget to deallocate
*ID = _ID;
} the memory!
}
};
Main + Output:
int main() {
BankAccount a;
BankAccount c(a);
cout << "Before Change:\n";
[Link]();
cout << endl;
[Link](99.99);
[Link](99.99);
[Link](99.99);
cout << "After Change:\n";
[Link]();
cout << endl;
[Link]();
cout << endl;
Shallow Copy | Deep Copy
Deep Copy:
Deep copy is possible only with user defined copy constructor.
In user defined copy constructor, we make sure that pointers (or references) of copied
object point to new memory locations.
Example – With Custom Copy
Constructor:
class BankAccount { void setID(double _ID) {
private: *ID = _ID;
double balance; }
double interest_rate; void setBalance(double _balance) {
double* ID; balance = _balance;
public: }
BankAccount() { //default constructor void setinterestRate(double _interest_rate) {
balance = 0.01; interest_rate = _interest_rate;
interest_rate = 0.01; }
ID = new double; void showDetails() {
*ID = 10.01; cout << "ID: " << *ID << "\nBal: " << balance <<
"\nIR: " << interest_rate;
}
}
BankAccount(const BankAccount &bankAccount) {
~BankAccount() {
balance = [Link];
cout << "Destructor is called\n";
interest_rate = bankAccount.interest_rate;
delete ID;
ID = new double;
*ID = *([Link]); Deep Copy! }
};
}
Main + Output:
int main() {
BankAccount a;
BankAccount c(a);
cout << "Before Change:\n";
[Link]();
cout << endl;
[Link](99.99);
[Link](99.99);
[Link](99.99);
cout << "After Change:\n";
[Link]();
cout << endl;
[Link]();
cout << endl;
Static Members – The “static”
Keyword
We can define class members static using the static keyword.
When we declare a member of a class as static it means no matter how many objects
of the class are created, there is only one copy of the static member.
A static member is shared by all objects of the class.
Static Members – How to Initialize?
It can be initialized outside the class using the scope resolution operator :: to identify
which class it belongs to.
All static data is initialized to zero when the first object is created, if no other
initialization is present.
Example:
class staticExample { int staticExample::count = 0;
static int count; int main()
public: {
staticExample() { staticExample a, b, c;
count++; cout << "No. of Objects: " << [Link]();
} staticExample d, e, f;
int getCount() { cout << endl;
return count; cout << "No. of Objects: " << [Link]();
}
}; return 0;
}
Initialization
Static Member Functions
By declaring a function member as static, you make it independent of any particular
object of the class
A static member function can be called even if no objects of the class exist and the
static functions are accessed using only the class name and the scope resolution
operator ( :: )
A static member function can only access static data member, other static member
functions and any other functions from outside the class.
Example
class staticExample { int staticExample::count = 0;
static int count;
public: int main()
staticExample() { { Invoking a static method
count++; without
cout << "Value from object
out creation
static
method: " <<
}
Static Member staticExample::getCount();
static int getCount() {
Function
return count;
return 0;
}
}
};
Things you can’t do:
class staticExample {
static int count;
int cantUseInStaticFunc;
public:
staticExample() {
count++;
}
int getCantUseInStaticFunc() {
return cantUseInStaticFunc;
}
static int getCount() {
cantUseInStaticFunc++;
int testFuncCall = getCantUseInStaticFunc();
return count;
}
Member Initialization Lists
Initializer List is used in initializing the data members of a class. The list of members to
be initialized is indicated with constructor as a comma-separated list followed by a
colon.
It is most relevant when we are trying to initialize a constant variable in our class. (for
now)
It will become important later with Inheritance, since we need it to initialize members
of the parent class!
Member Initialization Lists -
Example
class Point { In Main:
private: Point t1(10, 15);
int x; cout << "x = " << [Link]() << ", ";
int y; cout << "y = " << [Link]();
public:
Point(int i, int j) :x(i), y(j) {}
int getX() const { return x; }
int getY() const { return y; }
};
Default Values in Functions &
Constructors
You can provide default values for a function’s or a constructor’s arguments.
This makes it so that the values can be treated as optional
class Point {
private:
Here, default value for i
int x;
is 66, and for j it’s 77
int y;
public:
Point(int i = 66, int j = 77) :x(i), y(j) {}
int getX() const { return x; }
int getY() const { return y; }
};
Default Values in Functions &
Constructors
int main()
{
Point t1;
Point t2(88);
Point t3(99, 99);
cout << "x = " << [Link]() << ", ";
cout << "y = " << [Link]();
cout << “\nx = " << [Link]() << ", ";
cout << "y = " << [Link]();
cout << “\nx = " << [Link]() << ", ";
cout << "y = " << [Link]();
return 0;
}
More on default values
It’s not necessary for a function to have all default values.
In case other arguments do not have a default value, they must be at the start of the
argument list!
Point(int i = 66, int j)
int i = 66) ✓
Point(int j,
We can avoid having to write many overloaded constructors sometimes because of
this!
Constants – The “const” Keyword
Constant is something that doesn't change.
In C language and C++ we use the keyword const to make program elements
constant.
const keyword can be used in many contexts in a C++ program. It can be used with:
Variables
Pointers
Function Arguments
Class Data Members
Class Member Functions
Objects
Constant Variables
If you make any variable as constant, using const keyword, you cannot change its
value. Also, the constant variables must be initialized while they are declared.
const int cInt = 99;
cInt = 100; // gives an error!
const int cInt2; // gives an error!
Pointer to a Constant
The data pointed-to by the pointer will be considered a constant and cannot be changed.
The pointer can be reallocated / can point to other data
int val1 = 10;
int val2 = 20;
const int* ptr2C = &val1;
*ptr2c = 22; //invalid
ptr2c = &val2; //all good
Constant Pointer
The pointer points to a fixed memory location/ stores a memory address.
The value at that location can be changed because it is a variable.
The pointer itself cannot point to any other memory location / value of the memory
address cannot be changed.
int* const cPtr = &val1;
*cPtr = 22; // valid
cPtr = &val2; // invalid
Constant Pointer to a Constant
The data pointed-to by the pointer will be considered a constant and cannot be changed.
The pointer itself cannot point to any other memory location / value of the memory
address cannot be changed.
const int cInt1 = 1;
const int cInt2 = 2;
const int* const cPtr2C = &cInt1;
cPtr2C = &cInt2; // invalid
*cPtr2C = 3; // invalid
Constant Arguments in Functions
We can make the arguments of a function as const. Then we cannot change any of
them inside that function.
We saw an example of this in our copy constructor
You can also use them in setters when receiving pointers to an array etc.
void funcWithConstArg(const int cArg) {
cArg = 2020;
}
Constant Class Objects
When an object is declared or created using the const keyword, its data members can
never be changed, during the object's lifetime.
class constExample {
};
Above class will be initialized as a constant this way:
const constExample cObj;
Constant Member Functions in a
Class
A const member function never modifies data members in an object.
class constExample {
int testMember;
void constFunction(int testArg) const {
testArg++; //valid
testMember++;
};
Constant Member Variables in a
Class
These are data variables in class which are defined using const keyword. They are not
initialized during declaration. Their initialization is done in the constructor, only by using a
member initialization list!
class constExample {
int testMember;
const int mem;
public:
constExample() : mem(1000) {
}
constExample(int x) : mem(x) {
}
};
The “mutable” Keyword
mutable keyword is used with member variables of class, which we want to change
even if the object is of const type. Hence, mutable data members of a const object can
be modified.
Example:
class constMutableExample {
mutable int testMember;
int testMemberNM;
public:
constMutableExample() {
testMember = 10;
testMemberNM = 20;
}
void incBoth() const{ // const function, because a const object can only access const functions
testMember++;
testMemberNM++; //error because not mutable!
cout << "Mutable var: " << testMember;
cout << "\nNot mutable var: " << testMemberNM;
}
};
Example:
int main()
{
const constMutableExample ex;
[Link](); //do this after commenting out the error in previous code
return 0;
}
Fin.
:)