Professional Documents
Culture Documents
OOPS_Durvesh Jagtap_C++
OOPS_Durvesh Jagtap_C++
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() {…}
**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.
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)
**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;
}
// 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.
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;
}
};
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
// class
class GFG {
private:
int data;
public:
// parameterized constructor with default values
GFG(int x = 0) { data = x; }
int main()
{
GFG obj2(25);
cout << "First Object Data: " << obj1.getData() << endl;
cout << "Second Object Data: " << obj2.getData()
<< endl;
return 0;
}
Output
First Object Data: 0
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.
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;
Output
ID=10
ID=10
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; }
return 0;
}
**Implicit Copy constructor created only shallow copy, explicit I,e user defined copy constructor creates a deep copy
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.
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.
**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).
class BankAccount {
int accountNumber;
double balance;
static int totalAccounts;
public:
BankAccount(int number, double initialBalance): accountNumber(number), balance(initialBalance){
totalAccounts++;
}
void displayAccountDetails(){
cout << "Account Number: " << accountNumber << ", Balance: $" << balance << endl;
}
};
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
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 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() {
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.
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;
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.
public:
Test() { a = 1; }
// Driver code
int main()
{
Test obj;
int k = 3;
obj.func(k);
return 0;
} op: 1
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; }
};
// Driver code
int main()
{
Test obj;
int k = 3;
obj.func(k);
return 0;
} op: 1
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;
// Driver Code
int main() { return 0; }
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>
struct Test {
// x is public
int x;
};
int main()
{
Test t; //structure variable: an instance of a structure
t.x = 20;
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.
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) {}
int main() {
// Create a new bank account
BankAccount myAccount("1234567890", "John Doe");
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.
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.
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
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.
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;
}
};
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;
}
delete animal;
return 0;
}
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