Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 22

OOPS:

Classes and objects


Class is a blueprint of an object. (Class provides encapsulation of data members and member funcs)
Data members are the data variables and member functions are the functions used to manipulate these
variables together, these data members and member functions define the properties and behavior of the
objects in a Class.
EG: Car (4wheels, speed mileage) (applyBrakes, isFuelEmpty())
An Object is an instance of a Class. When a class is defined, no memory is allocated but when it is
instantiated (i.e. an object is created) memory is allocated.
ClassName obj; obj.functionName, obj.varName;

Special Member functions:

Constructors: default, params, copy: called by compiler when the object of that class is instantiated
Destructor: called by the compiler when the scope of an object ends
~ClassName() {…}

member access operator (.)

**The semicolon ; at the end of the class definition is necessary to inform the compiler that the class
definition is finished. It's a syntactic requirement of the C++ language.

If you omit the semicolon at the end of the class definition, the compiler will raise a syntax error because it
expects a semicolon to terminate the class declaration.

Access Modifiers in C++


Access modifiers are used to implement an important aspect of Object-Oriented Programming known as
Data Hiding.
There are 3 types of access modifiers available in C++:
Public
Private
Protected
Note: If we do not specify any access modifiers for the members inside the class, then by default the
access modifier for the members will be Private.

Real time EG: The Research and Analysis Wing (R&AW), having 10 core members, has come into
possession of sensitive confidential information regarding national security. Now we can correlate these core
members to data members or member functions of a class, which in turn can be correlated to the R&A Wing.
These 10 members can directly access the confidential information from their wing (the class), but anyone
apart from these 10 members can’t access this information directly, i.e., outside functions other than those
prevalent in the class itself can’t access the information (that is not entitled to them) without having either
assigned privileges.
Private:
Member function inside the class can only access private data members.
Outside object or function cannot directly access it using member access pointer(.) (exception: friend
function)

In function 'int main()':


11:16: error: 'double Circle::radius' is private
double radius;
^
31:9: error: within this context
obj.radius = 1.5;

**However, we can access the private data members of a class indirectly using the public member functions
of the class.

Protected: the class members declared as Protected can be accessed by any subclass (derived class) of that
class as well.
Friend Class and Function in C++
A friend class can access private and protected members of other classes in which it is declared as a friend. It
is sometimes useful to allow a particular class to access private and protected members of other classes.

Syntax:
friend class class_name; // declared in the base class
// C++ Program to demonstrate the
// functioning of a friend class
#include <iostream>
using namespace std;

class GFG {
private:
int private_variable;

protected:
int protected_variable;

public:
GFG()
{
private_variable = 10;
protected_variable = 99;
}

// friend class declaration


friend class F;
};

// Here, class F is declared as a


// friend inside class GFG. Therefore,
// F is a friend of class GFG. Class F
// can access the private members of
// class GFG.
class F {
public:
void display(GFG& t)
{
cout << "The value of Private Variable = "
<< t.private_variable << endl;
cout << "The value of Protected Variable = "
<< t.protected_variable;
}
};

// Driver code
int main()
{
GFG g;
F fri;
fri.display(g);
return 0;
}
When an object of the GFG class (g in this case) is passed by reference to the display function, the function
parameter t receives a reference to the same memory location as the original object g. This means that t
essentially becomes an alias for g.

So, any changes made to t inside the display function will directly affect the original object g, because they
both refer to the same memory location.

Friend Function:

Syntax:
friend return_type function_name (arguments); // for a global function
or
friend return_type class_name::function_name (arguments); // for a member function of another class

**A friend function is called like an ordinary function. It cannot be called using the object name and
dot operator. However, it may accept the object as an argument whose value it wants to access.
**Another class member function is defined as a friend can also access private and protected
members of a class in C++;
https://www.geeksforgeeks.org/friend-class-function-cpp/?ref=next_article
Constructors in c++
 Constructor is a special type of member function that is used to initialize the data members for an
object of a class automatically when an object of the same class is created.
 Constructors do not return value, hence they do not have a return type.
 A constructor gets called automatically when we create the object of the class.
 Constructors can be overloaded.
 A constructor can not be declared virtual.
 A constructor cannot be inherited.
 The constructor makes implicit calls to new and delete operators during memory allocation.

Syntax for Defining the Constructor Outside the Class


<class-name>: :<class-name>(list-of-parameters)
{
// constructor definition
}

Real EG:
Let us understand the types of constructors in C++ by taking a real-world example. Suppose you went to a
shop to buy a marker. When you want to buy a marker, what are the options? The first one you go to a shop
and say give me a marker. So just saying give me a marker means that you did not set which brand name and
which color, you didn’t mention anything just say you want a marker. So when we said just I want a marker
whatever the frequently sold marker is there in the market or his shop he will simply hand over that. And
this is what a default constructor is!

The second method is you go to a shop and say I want a marker red in color and XYZ brand. So you are
mentioning this and he will give you that marker. So in this case you have given the parameters. And this is
what a parameterized constructor is!

Then the third one you go to a shop and say I want a marker like this(a physical marker on your hand). So
the shopkeeper will see that marker. Okay, and he will give a new marker for you. So copy of that marker.
And that’s what a copy constructor is!

Now, assume that you don’t to buy a new marker but instead take ownership of your friend’s marker. It
means taking ownership of already present resources instead of getting a new one. That’s what a move
constructor is!

1. Default
Note: Even if we do not define any constructor explicitly, the compiler will automatically provide a
default constructor implicitly.

The implicit default constructor provided by the compiler is useful in several scenarios, even if you
do not define any constructor explicitly in your class. Here are some of the key uses and reasons
why the default constructor is important:

Case1: The default constructor initializes the object of the class with default values, which is essential for
the correct behavior of the program.
class Example {
public:
int data;
// No constructor defined
};

int main() {
Example obj; // Default constructor is called
cout << obj.data; // Outputs default-initialized value (typically garbage value)
return 0;
}

2. Inheritance
When you have derived classes, the default constructor of the base class is called automatically by the
derived class's constructor.

class Base {
public:
Base() {
cout << "Base class constructor" << endl;
}
};

class Derived : public Base {


public:
Derived() {
cout << "Derived class constructor" << endl;
}
};

int main() {
Derived d; // Outputs: Base class constructor
// Derived class constructor
return 0;
}

4. Array of Objects
When you create an array of objects, the default constructor is used to initialize each object in the array.
class Example {
public:
Example() {
cout << "Default constructor called" << endl;
}
};

int main() {
Example arr[3]; // Outputs: Default constructor called
// Default constructor called
// Default constructor called
return 0;
}
IMP: Parameterized Constructor with default values

Default Arguments with C++ Parameterized Constructor

// C++ Program to illustrate how to use default arguments


// with parameterized constructor
#include <iostream>
using namespace std;

// class
class GFG {
private:
int data;

public:
// parameterized constructor with default values
GFG(int x = 0) { data = x; }

int getData() { return data; }


};

int main()
{

GFG obj1; // will not throw error

GFG obj2(25);

cout << "First Object Data: " << obj1.getData() << endl;
cout << "Second Object Data: " << obj2.getData()
<< endl;

return 0;
}

Output
First Object Data: 0

Second Object Data: 25

As we can see, when the default values are assigned to every argument of the parameterized constructor, it is legal to create the object
without passing any parameters just like default constructors. So, this type of constructor works as both a default and parameterized
constructor.

**Just like the default constructor, the C++ compiler also provides an implicit copy constructor if the explicit copy constructor
definition is not present. Here, it is to be noted that, unlike the default constructor where the presence of any type of explicit
constructor results in the deletion of the implicit default constructor, the implicit copy constructor will always be created by the
compiler if there is no explicit copy constructor or explicit move constructor is present.

IMP: Copy Constructors

Copy constructor takes a reference to an object of the same class as an argument.


ClassName (ClassName &obj)
{
// body_containing_logic
}

Implicit Copy Constructor

// C++ program to illustrate the use of Implicit copy


// constructor
#include <iostream>
using namespace std;

class Sample {
int id;

public:
// parameterized constructor
Sample(int x) { id = x; }
void display() { cout << "ID=" << id; }
};

int main()
{
Sample obj1(10);
obj1.display();
cout << endl;

// creating an object of type Sample from the obj


Sample obj2(obj1); // or obj2=obj1;
obj2.display();
return 0;
}

Output
ID=10
ID=10

Explicit Copy Constructor


// C++ Program to demonstrate how to define the explicit
// copy constructor
#include <iostream>
using namespace std;

class Sample {
int id;

public:
// default constructor with empty body
Sample() {}

// parameterized constructor
Sample(int x) { id = x; }

// copy constructor
Sample(Sample& t) { id = t.id; }

void display() { cout << "ID=" << id; }


};
// driver code
int main()
{
Sample obj1(10);
obj1.display();
cout << endl;

// copy constructor called


Sample obj2(obj1); // or obj2=obj1;
obj2.display();

return 0;
}

**Implicit Copy constructor created only shallow copy, explicit I,e user defined copy constructor creates a deep copy

4. Move Constructor in C++

The move constructor is a recent addition to the family of constructors in C++. It is like a copy constructor
that constructs the object from the already existing objects., but instead of copying the object in the new
memory, it makes use of move semantics to transfer the ownership of the already created object to the new
object without creating extra copies.

Syntax of Move Constructor in C++


className (className&& obj) {
// body of the constructor
}

Static members in c++


Static Members in C++

In C++, a static member of a class is shared by all objects of the class. Unlike instance members,
which belong to individual objects, static members belong to the class itself. They are initialized
only once at the start of the program execution and retain their values across different objects of
the class.

Here are some key points about static members:

 A static member can be a data member or a member function.


 It is declared using the static keyword.
 A static data member is shared among all objects of the class.
 A static member function can only access static data members and can be called using the
class name without creating an object.

**Static variables are useful when you want to maintain a value across all objects of a class or when
you want to have a variable that is independent of any particular object of the class.

**
1. Making the Memory of the Variable Static
When you declare a variable as static inside a function or a class, it means that the variable will be
stored in a static memory location, rather than on the stack (for local variables) or the heap (for
dynamic memory).

2. Memory Can't Be Changed


The memory for a static variable is allocated once and retains its value across function calls or
object instances. This is what is meant by "its memory can't be changed."

Real Life EG:


//real life: Bank Account Scenario
#include <iostream>
using namespace std;

class BankAccount {
int accountNumber;
double balance;
static int totalAccounts;

public:
BankAccount(int number, double initialBalance): accountNumber(number), balance(initialBalance){
totalAccounts++;
}

static void displayAccountCount(){


cout << "Total Account Count: " << totalAccounts << endl;
}

void displayAccountDetails(){
cout << "Account Number: " << accountNumber << ", Balance: $" << balance << endl;
}
};

//set initial value of static data member


int BankAccount::totalAccounts = 0;

int main()
{
BankAccount a1(1001, 20000.22);
BankAccount a2(1002, 200220.22);
BankAccount a3(1004, 40000.22);

a1.displayAccountDetails();
a2.displayAccountDetails();
a3.displayAccountDetails();

BankAccount::displayAccountCount();
return 0;
}

Output:
Account Number: 1001, Balance: $20000.2
Account Number: 1002, Balance: $200220
Account Number: 1004, Balance: $40000.2
Total Account Count: 3

This pointer in C++


How Objects Access Functions and Data Members

When you create an object of a class, each object has its own set of data members, but they all
share the same member functions.

The Problem

Since all objects share the same member functions, how does each object know which data
members to access or modify?

The Solution: 'this' Pointer

The this pointer is a special pointer that the compiler provides to every non-static member
function. It points to the object that called the function.

Simple Explanation:

Imagine you have a class called Car with a member function called drive(). Each Car object has its
own speed, but they all use the same drive() function.

class Car {

private:

int speed;

public:

Car(int s) : speed(s) {}

void drive() {

// How does this function know which car's speed to use?

cout << "Driving at speed: " << speed << " mph" << endl;

};

When you call drive() on a Car object, the this pointer is automatically passed to the function,
telling it which Car object is calling it.

Car myCar(60);
myCar.drive(); // Output: Driving at speed: 60 mph

In this example, this is pointing to myCar inside the drive() function, so it knows to use myCar's
speed of 60 mph.

Key Points:

 The this pointer is a hidden pointer that points to the object that called the member
function.
 It allows each object to access its own data members, even when they are using the same
member function.
 this is not available in static member functions because they don't belong to any specific
object.

Simple Explanation Summary:

The this pointer is like a secret assistant that tells each member function which object it belongs to,
so it can access and modify that object's data members correctly.

Eg2:

#include<iostream>
using namespace std;

/* local variable is same as a member's name */


class Test
{
private:
int x;
public:
void setX (int x)
{
// The 'this' pointer is used to retrieve the object's x
// hidden by the local variable 'x'
this->x = x;
}
void print() { cout << "x = " << x << endl; }
};

int main()
{
Test obj;
int x = 20;
obj.setX(x);
obj.print();
return 0;
}
OP: 20
Scope Resolution operator vs this pointer in C++
Scope resolution operator is for accessing static or class members and this pointer is for accessing object
members when there is a local variable with the same name.

In case of same name ie shadowing


// C++ program to show use of this to access member when
// there is a local variable with same name
#include <iostream>
using namespace std;
class Test {
int a;

public:
Test() { a = 1; }

// Local parameter 'a' hides object's member


// 'a', but we can access it using this.
void func(int a) { cout << this->a; }
};

// Driver code
int main()
{
Test obj;
int k = 3;
obj.func(k);
return 0;
} op: 1

In case of shadowing, using scope resolution operator


// C++ program to show that scope resolution operator can be
// used to access static members when there is a local
// variable with same name
#include <iostream>
using namespace std;

class Test {
static int a;

public:
// Local parameter 'a' hides class member
// 'a', but we can access it using ::
void func(int a) { cout << Test::a; }
};

// In C++, static members must be explicitly defined


// like this
int Test::a = 1;

// Driver code
int main()
{
Test obj;
int k = 3;
obj.func(k);
return 0;
} op: 1

// Local Classes in C++ (NSI)

A class declared inside a function becomes local to that function and is called Local Class in C++.

 A local class name can only be used locally i.e., inside the function and not outside it.
 The methods of a local class must be defined inside it only.
 A local class can have static functions but, not static data members.

**TODO:
// C++ program without any compilation error
// to demonstrate a Local Class
#include <iostream>
using namespace std;

// Creating the class


void fun()
{
// local to fun
class Test {
// members of Test class
};
}

// Driver Code
int main() { return 0; }

// Nested Classes in C++ (NSI)


A nested class is a class which is declared in another enclosing class. A nested class is a member and as such
has the same access rights as any other member. The members of an enclosing class have no special access
to members of a nested class; the usual access rules shall be obeyed.
nested class can access private members of Enclosing class

// ENUM CLASS in C++


https://www.geeksforgeeks.org/enum-classes-in-c-and-their-advantage-over-enum-datatype/?
ref=next_article

Difference between Structure and Class in C++


https://www.geeksforgeeks.org/structure-vs-class-in-cpp/?ref=lbp

- Inheritance is supported in both Classes as well as structures


- Default access mode of members is private in CLASS and public in STRUCTURE
- Class keyword, struct keyword
- Struct: Grouping of data, Class: data abstraction and Inheritance
- Instance of CLASS: object Instance of Structure: structure variable

Both struct and class do not automatically set member variables to null. They will contain garbage values if
not initialized.

Struct:
// C++ Program to demonstrate that
// members of a structure are public
// by default
#include <iostream>

using namespace std;

struct Test {
// x is public
int x;
};

int main()
{
Test t; //structure variable: an instance of a structure
t.x = 20;

// works fine because x is public


cout << t.x;
}

IMP: WHY CPP IS PARTIAL OOP LANGUAGE?


The main function is outside of class
Concept of global variable
Concept of friend function
V.IMP: PILLARS OF OOP
ENCAPSULATION and ABSTRACTION:

Real-Life Scenario: Bank Account Management

Imagine you are developing a simple bank account management system. Each bank account has a
balance, account number, and owner's name. For security and data integrity reasons, you want to
encapsulate the bank account's data and provide controlled access to it. You also want to ensure
that the balance cannot be directly modified from outside the class, but only through specific
methods.

Encapsulation in C++: Bank Account Class

Here's a C++ code example that demonstrates encapsulation for the bank account management
system:

#include <iostream>
#include <string>

class BankAccount {
private:
std::string accountNumber;
std::string ownerName;
double balance;

public:
// Constructor
BankAccount(const std::string& accNumber, const std::string& owner)
: accountNumber(accNumber), ownerName(owner), balance(0.0) {}

// Public methods to access and modify private members


void deposit(double amount) {
if (amount > 0) {
balance += amount;
std::cout << "Deposited $" << amount << ". New balance is $" << balance << std::endl;
} else {
std::cout << "Invalid deposit amount." << std::endl;
}
}

void withdraw(double amount) {


if (amount > 0 && amount <= balance) {
balance -= amount;
std::cout << "Withdrawn $" << amount << ". New balance is $" << balance << std::endl;
} else {
std::cout << "Invalid withdrawal amount or insufficient funds." << std::endl;
}
}

double getBalance() const {


return balance;
}

std::string getAccountNumber() const {


return accountNumber;
}

std::string getOwnerName() const {


return ownerName;
}

// Method to display account details


void display() const {
std::cout << "Account Number: " << accountNumber << std::endl;
std::cout << "Owner Name: " << ownerName << std::endl;
std::cout << "Balance: $" << balance << std::endl;
}
};

int main() {
// Create a new bank account
BankAccount myAccount("1234567890", "John Doe");

// Display initial account details


std::cout << "Initial Account Details:" << std::endl;
myAccount.display();

// Deposit and withdraw money


myAccount.deposit(1000);
myAccount.withdraw(500);

// Display updated account details


std::cout << "\nUpdated Account Details:" << std::endl;
myAccount.display();

return 0;
}

Note: In C++, the const keyword after a member function declaration indicates that the member
function does not modify any non-static data members of the class. This is a promise or contract
from the function to the caller that the function will not change the state of the object it is called on.

Explanation of above code:

 The BankAccount class encapsulates the account number, owner's name, and balance as
private members.
 Public methods like deposit, withdraw, getBalance, getAccountNumber, and getOwnerName provide
controlled access to the private members, allowing clients to interact with the bank account
in a controlled manner without directly accessing or modifying its private data.

By using encapsulation, we ensure data integrity, maintainability, and provide a clear interface for
interacting with the bank account objects.

Two Important property of Encapsulation

Data Protection: Encapsulation protects the internal state of an object by keeping its data members private.
Access to and modification of these data members is restricted to the class’s public methods, ensuring
controlled and secure data manipulation.
Information Hiding: Encapsulation hides the internal implementation details of a class from external code.
Only the public interface of the class is accessible, providing abstraction and simplifying the usage of the
class while allowing the internal implementation to be modified without impacting external code.

The function which we are making inside the class must use only member variables, only then it is called
encapsulation.
If we don’t make a function inside the class which is using the member variable of the class then we don’t
call it encapsulation.
Encapsulation improves readability, maintainability, and security by grouping data and methods together.
It helps to control the modification of our data members.

Summary:
 Binding together data and functions that operate on that data into a single unit called Class.
 Controlled access to data members (maintains the internal state of the object): and exposes only
necessary functionality (public methods) to interact with the object

 Hiding relevant data using access specifiers.


 The function that we are making inside the class must use only member variables, only then it is
called encapsulation.

Abstraction in C++
Abstraction means displaying only essential information and hiding the details.
Data abstraction refers to providing only essential information about the data to the outside world, hiding the
background details or implementation.
Abstraction in object-oriented programming (OOP) allows us to provide a simplified and clear interface to
interact with objects while hiding complex implementation details.

Types of Abstraction:
Data abstraction – This type only shows the required information about the data and hides the unnecessary
data.
Control Abstraction – This type only shows the required information about the implementation and hides
unnecessary information.

Abstraction using Classes


We can implement Abstraction in C++ using classes. The class helps us to group data members and member
functions using available access specifiers. A Class can decide which data member will be visible to the
outside world and which is not.
Abstraction in Header files
One more type of abstraction in C++ can be header files. For example, consider the pow() method present in
math.h header file. Whenever we need to calculate the power of a number, we simply call the function pow()
present in the math.h header file and pass the numbers as arguments without knowing the underlying
algorithm according to which the function is actually calculating the power of numbers.

VIMP: Polymorphism in C++


Polymorphism:
 Polymorphism means "many shapes," and in OOP, it refers to the ability to present the same interface for
different data types or objects.
 In this example, the base pointer of type GFG_Base* can point to objects of both GFG_Base and GFG_Child
classes.
Virtual Functions:
 Virtual functions allow a derived class to provide its own implementation of a method that is already
defined in a base class.
 In this example, the display() function is declared as virtual in the base class, allowing the GFG_Child class
to override it.
 The print() function is not declared as virtual, so it won't be overridden in the derived class.
Late Binding (Dynamic Binding):
 Late binding means that the actual method to call is determined at runtime based on the runtime type of
the object, not the reference or pointer type.
 In this example, when base->display(); is called, the display() method of the GFG_Child class is executed
because the base pointer points to an object of the GFG_Child class at runtime, and the method is virtual.
Early Binding (Static Binding):
 Early binding means that the decision about which method to call is made at compile time based on the
reference or pointer type, not the runtime type of the object.
 In this example, when base->print(); is called, the print() method of the GFG_Base class is executed because
the method is not virtual, and the decision is made based on the pointer type ( GFG_Base*).

 Early binding (compile-time binding) is used for non-virtual functions, where the decision
about which method to call is made at compile time based on the reference or pointer type.
 Late binding (runtime binding) is used for virtual functions, where the actual method to call is
determined at runtime based on the runtime type of the object.

Summary:

 Polymorphism allows a base class pointer to point to objects of both base and derived classes.
 Virtual functions enable late binding, where the actual method to call is determined at runtime based on
the runtime type of the object.
 Non-virtual functions use early binding, where the decision about which method to call is made at
compile time based on the reference or pointer type.

This concept of using base class pointers to achieve polymorphism and late binding is a powerful feature in
object-oriented programming, allowing for flexible, extensible, and maintainable code.
Real-time Short Scenario Example:
Scenario: Animal Sounds in a Zoo
Imagine you are developing software to simulate the sounds animals make in a zoo. You have a
base class Animal and derived classes Dog, Cat, and Bird, each with their own implementation of the
makeSound() method. At runtime, based on the type of animal selected by the user, the
corresponding makeSound() method should be executed to play the sound of that animal.

#include <iostream>

// Base class
class Animal {
public:
virtual void makeSound() {
std::cout << "An animal makes a sound" << std::endl;
}
};

// Derived class Dog


class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Dog barks" << std::endl;
}
};

// Derived class Cat


class Cat : public Animal {
public:
void makeSound() override {
std::cout << "Cat meows" << std::endl;
}
};

// Derived class Bird


class Bird : public Animal {
public:
void makeSound() override {
std::cout << "Bird chirps" << std::endl;
}
};

int main() {
Animal* animal;

int choice;
std::cout << "Select an animal (1: Dog, 2: Cat, 3: Bird): ";
std::cin >> choice;

switch (choice) {
case 1:
animal = new Dog();
break;
case 2:
animal = new Cat();
break;
case 3:
animal = new Bird();
break;
default:
std::cout << "Invalid choice" << std::endl;
return 1;
}

// Play the sound of the selected animal


animal->makeSound();

delete animal;
return 0;
}

FUNCTION OVERIDDING IN C++

Function Overloading Function Overriding

It falls under Compile-Time polymorphism It falls under Runtime Polymorphism

A function can be overloaded multiple times as A function cannot be overridden multiple times
it is resolved at Compile time as it is resolved at Run time

Can be executed without inheritance Cannot be executed without inheritance

They are in the same scope They are of different scopes.

Overloading: same name, different parameters, same class


Overidding: same name, same params, different class (Inheritance)

You might also like