Constructor and Destructor in C++.

Constructor and Destructor in C++ are the special member functions of the class and they are essential components of Object Oriented Programming. Constructors are special functions within a class that initialize the object when it is created, providing default or custom values to its attributes. On the other hand, destructors are used to clean up resources allocated by the object during its lifetime, and they are automatically invoked when the object goes out of scope or is explicitly deleted.

Constructor and Destructor in C++

What is a Constructor in C++?

A constructor in C++ is a special member function of a class that is automatically invoked when an object of that class is created. Its primary purpose is to initialize the object's attributes or perform any necessary setup. Constructors have the same name as the class and do not have a return type. 


There are many types of constructors available in C++. When an object is instantiated, the appropriate constructor is automatically called, ensuring that the object is properly initialized before it is used. Constructors play a crucial role in object-oriented programming by establishing the initial state of objects.


How many types of constructors in C++?

There are basically four types of constructors present in C++ and these are:

  • Default Constructor.
  • Parameterized Constructor.
  • Copy Constructor.
  • Dynamic Constructor.
Let's discuss each of them in detail one by one,


Default Constructor.

A default constructor in C++ is a constructor that takes no parameters. It is automatically generated by the compiler if no constructor is explicitly defined in the class. It is called when an object is created with no arguments.

Syntax:
class ClassName {
public:
    ClassName() {
        // Constructor code
    }
};

Example Code for Default Constructor:
// C++ code implementation for default constructor
#include <iostream>
using namespace std;

class MyClass {
private:
    int rollNo;
    string name;

public:
    // Default Constructor
    MyClass() {
        std::cout << "Default Constructor Called" << std::endl;
        rollNo = 0;
        name = "NULL";
    }

    void display(){
        cout << "Student Name: " << name << endl;
        cout << "Roll No: " << rollNo << endl;
    }
};

int main() {
    // Creating an object invokes the default constructor
    MyClass obj;  

    obj.display();
    return 0;
}
Output:
Default Constructor Called
Student Name: NULL
Roll No: 0

In the above example, we created a class MyClass with a default constructor to initialize the initial values to data members of the class, and the default constructor is called as soon as we create the object of that class obj
Note: It's important to explicitly define a default constructor when custom initialization is required or when other constructors are defined in the class. (alert-passed)

Parameterized Constructor.

A parameterized constructor in C++ is a constructor that accepts parameters during its invocation. It allows you to initialize the object with specific values based on the provided arguments. 

Syntax:
class ClassName {
public:
    ClassName(type1 param1, type2 param2, ...) {
        // Constructor code
    }
};

Example Code for Parameterized Constructor:
// C++ code implementation for Parameterized constructor
#include <iostream>
using namespace std;

class Car {
private:
    string brand;
    int year;

public:
    // Parameterized Constructor
    Car(string b, int y) {
        cout << "Parameterized Constructor Called" << endl;
        brand = b;
        year = y;
    }

    void display() {
        cout << "Brand: " << brand << ", Year: " << year << endl;
    }
};

int main() {
    // Creating an object using the parameterized constructor
    Car myCar("Toyota", 2022);
    myCar.display();  
    return 0;
}
Output:
Parameterized Constructor Called
Brand: Toyota, Year: 2022

In the above example, the parameterized constructor takes parameters (in this case, a string and an integer) during its declaration. The constructor is called when an object is created, allowing custom initialization based on the provided arguments.

Copy Constructor.

A copy constructor in C++ is a special type of constructor that is used to create a new object as a copy of an existing object of the same class. It is invoked when an object is passed by value or returned by value.
Note: If a copy constructor is not explicitly defined, the compiler generates a default copy constructor. (alert-success)
Syntax:
class ClassName {
public:
    // Copy Constructor
    ClassName(const ClassName& obj) {
        // Constructor code
    }
};

Example Code for Copy Constructor:
// C++ code implementation for Copy constructor
#include <iostream>
using namespace std;

class Student {
private:
    string name;
    int age;

public:
    // Parameterized Constructor
    Student(string n, int a) : name(n), age(a) {
        cout << "Parameterized Constructor Called" << endl;
    }

    // Copy Constructor
    Student(const Student& obj) : name(obj.name), age(obj.age) {
        cout << "Copy Constructor Called" << endl;
    }

    void display() {
        cout << "Name: " << name << ", Age: " << age << endl;
    }
};

int main() {
    // Creating an object using the parameterized constructor
    Student originalStudent("John", 20);
    originalStudent.display();  

    // Creating a new object using the copy constructor
    Student copiedStudent = originalStudent;
    copiedStudent.display();  
    
    return 0;
}
Output:
Name: John, Age: 20
Copy Constructor Called
Name: John, Age: 20

In the above example, the copy constructor takes a reference to an object of the same class (const ClassName& obj) as its parameter. It initializes the members of the new object with the values of the corresponding members of the existing object.

Dynamic Constructor.

In C++, a dynamic constructor is not a distinct type of constructor. Constructors are typically classified based on their parameters and use cases, such as default constructors, parameterized constructors, and copy constructors. However, there might be a misunderstanding or miscommunication about the term "dynamic constructor."

If you are referring to dynamic memory allocation within a constructor (e.g., using new), this is a common practice in C++ but doesn't give rise to a separate category of a constructor. 

What is a Destructor in C++?

A destructor in C++ is a special member function of a class that is executed whenever an object of the class goes out of scope or is explicitly deleted. It is used to release resources or perform cleanup operations associated with the object before it is destroyed.

Syntax:
class ClassName {
public:
    // Constructor(s)
    ClassName(); // Default constructor
    ClassName(parameters); // Parameterized constructor

    // Destructor
    ~ClassName(); 
};

Key points about Destructor:
  • A destructor has the same name as the class but is prefixed with a tilde (~).
  • Unlike constructors, which can be overloaded, a class can have only one destructor.
  • The destructor is automatically invoked when an object goes out of scope or is explicitly deleted.
  • It is used for releasing resources, closing files, releasing memory, or performing any cleanup necessary before the object is destroyed.

Example Code for Destructor in C++:
// C++ code implementation for Destructor
#include <iostream>
using namespace std;

class MyClass {
public:
    // Constructor
    MyClass() {
        std::cout << "Constructor Called" << std::endl;
    }

    // Destructor
    ~MyClass() {
        std::cout << "Destructor Called" << std::endl;
    }
};

int main() {
    // Creating an object
    MyClass obj; 

    // Object goes out of scope, destructor is called
    return 0;
}
Output:
Constructor Called
Destructor Called
Note: In the example, the destructor prints a message for demonstration purposes. In real-world scenarios, destructors are often used to deallocate memory, close files, or release other resources.(alert-passed)

 (getButton) #text=(Access Specifiers in C++) #icon=(link) #color=(#2339bd)

Program to Move All Zeroes to the End of Array.

Given an integer array arr[] of size n, the task is to move all zeroes (0's) to the end of the array while maintaining the relative order of non-zero elements.

Example:

Input: arr[] = {0, 1, 0, 3, 5, 0}
Output: arr[] = {1, 3, 5, 0, 0, 0}

Input: arr[] = {0, 1}
Output: arr[] = {1, 0}

There are multiple approaches to solving this problem. Let's discuss each approach one by one from brute force to optimized one.

Approach 1: Brute Force Approach.

This is a basic approach in which we are going to traverse the complete array to store all non-zero elements in the front of the new array and add the required number of zeroes at the end. Below are the steps to follow: 
  • Create a new array.
  • Iterate through the original array.
  • For each non-zero element, add it to the new array.
  • After completing the iteration, add the required number of zeros to the new array.
  • The new array will now have all non-zero elements followed by zeros.
Below is the C++ code implementation for the above approach:
//C++ code to move all zeroes at the end of array
#include <bits/stdc++.h>
using namespace std;

vector<int> moveZeroesBruteForce(vector<int>& arr) {
    vector<int> result;

    for (int i : arr) {
        if (i != 0) {
            result.push_back(i);
        }
    }
    //count of 0's present in the array
    int numberOfZeroes = arr.size() - result.size();
    result.insert(result.end(), numberOfZeroes, 0);

    return result;
}

int main(){
    vector<int> arr = {0, 1, 0, 3, 4, 0, 0, 8};

    vector<int> ans = moveZeroesBruteForce(arr);

    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] <<" ";
    }

    return 0;
}
Output:
1 3 4 8 0 0 0 0 
  • Time Complexity: O(n) where n is the number of elements present in the array.
  • Space Complexity: O(n) where n is the number of elements present in the array.


Approach 2: Optimized Approach. 

This is an in-place approach in which we are not going to use any extra space to move all 0s to the end of the array. Below are the steps to follow:
  • Initialize a variable to keep track of the position to overwrite.
  • Iterate through the array.
  • For each non-zero element, overwrite the next position with the current element.
  • After completing the iteration, fill the remaining positions with zeros.
  • The array will now have all non-zero elements followed by zeros. 
Below is the C++ code implementation for the above approach:
//C++ code to move all zeroes at the end of array
//In-place approach
#include <bits/stdc++.h>
using namespace std;

vector<int> moveZeroesOptimized(vector<int>& arr) {
    int writeIndex = 0; // Position to overwrite

    for (int i : arr) {
        if (i != 0) {
            arr[writeIndex++] = i;
        }
    }

    // Fill the remaining positions with zeros
    while (writeIndex < arr.size()) {
        arr[writeIndex++] = 0;
    }

    return arr;
}

int main(){
    vector<int> arr = {0, 1, 0, 3, 4, 0, 0, 8};

    vector<int> ans = moveZeroesOptimized(arr);

    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] <<" ";
    }

    return 0;
}
Output:
1 3 4 8 0 0 0 0 
  • Time Complexity: O(n) where n is the number of elements present in the array.
  • Space Complexity: O(1) as no extra space is required to solve the problem using this approach.

Approach 3: Two Pointer Approach.

In this approach, we use two pointers, one to iterate through the array and the next the keep track of position for non-zero values. Below are the steps that need to be followed:
  • Use two pointers - one to iterate through the array and another to keep track of the position to overwrite.
  • Iterate through the array.
  • For each non-zero element, swap it with the element at the position to overwrite.
  • After completing the iteration, the array will have all non-zero elements followed by zeros.
Below is the C++ code implementation for the above approach:
//C++ code to move all zeroes at the end of array
//In-place two pointer approach
#include <bits/stdc++.h>
using namespace std;

vector<int> moveZeroesTwoPointer(vector<int>& arr) {
    int writeIndex = 0; // Position to overwrite

    for (int i = 0; i < arr.size(); ++i) {
        if (arr[i] != 0) {
            std::swap(arr[writeIndex++], arr[i]);
        }
    }

    return arr;
}

int main(){
    vector<int> arr = {0, 1, 0, 3, 4, 0, 0, 8};

    vector<int> ans = moveZeroesTwoPointer(arr);

    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] <<" ";
    }

    return 0;
}
Output:
1 3 4 8 0 0 0 0 
  • Time Complexity: O(n) where n is the number of elements present in the array.
  • Space Complexity: O(1) as no extra space is required to solve the problem using this approach.
I hope you understood all three approaches to solving this problem of moving 0s to the end of the given array. 

Program to Remove Duplicate From Sorted Array in C++.

Given an integer array arr[] sorted in ascending order, the task is to remove duplicate elements such that the relative order of the elements should be kept the same. 

Example:
Input: arr[] = {1, 1, 2, 2, 2, 3}
Output: arr[] = {1, 2, 3}

Input: arr[] = {1, 2, 5, 5}
Output: arr[] = {1, 2, 5}

There are multiple ways to solve this problem, let's discuss each of them one by one:

Approach 1: Brute Force Approach.

It is the simplest approach in which we are going to use extra space to store only unique elements. Below are the steps to follow:
  • Create a new array temp[].
  • Iterate through the original array arr[].
  • For each element, check if it is already present in the new array.
  • If not, add it to the new array.
  • The new array contains elements without duplicates.
At the end, you can copy the elements of the new array into the original array and return the original array.

Note: In the below code we have used std::vector() instead of the array because in real-world problems and in interviews we have to deal with vectors.   

Example Code: Below is the C++ code implementation for the above approach.
//C++ code to remove duplicate elements from the array
#include <bits/stdc++.h>
using namespace std;

int removeDuplicatesBruteForce(vector<int>& arr) {
    vector<int> result;

    for (int i : arr) {
        //checking if element already exist
        if (find(result.begin(), result.end(), i) == result.end()) {
            result.push_back(i);
        }
    }
    arr = result;
    return result.size();
}

int main(){
    vector<int> arr = {1, 1, 2, 2, 2, 3, 5};

    int n = removeDuplicatesBruteForce(arr);

    for(int i = 0; i < n; i++){
        cout << arr[i] <<" ";
    }

    return 0;
}
Output:
1 2 3 5
  • Time Complexity: O(n^2) where n is the number of elements in the array.
  • Space Complexity: O(n) where n is the number of elements in the array.

Approach 2: Optimized Approach.

In this approach, we are going to iterate the complete array only once to find all unique elements. Below are the steps to be followed:
  • Create a result vector and add the first element of the array.
  • Iterate through the original array from the second element.
  • For each element, check if it is equal to the previous element.
  • If not, add it to the result vector.
  • The result vector will now contain elements without duplicates.
Example Code: Below is the C++ code implementation for the above approach.
//C++ code to remove duplicate elements from the array
#include <bits/stdc++.h>
using namespace std;

int removeDuplicatesOptimized(vector<int>& arr) {
    vector<int> result;

    if (!arr.empty()) {
        //add first element to array
        result.push_back(arr[0]);

        for (size_t i = 1; i < arr.size(); ++i) {
            //check if element is equal to previous element
            if (arr[i] != arr[i - 1]) {
                result.push_back(arr[i]);
            }
        }
    }
    //copy unique elements to original array
    arr = result;
    return result.size();
}

int main(){
    vector<int> arr = {1, 1, 2, 2, 2, 2, 5};

    int n = removeDuplicatesOptimized(arr);

    for(int i = 0; i < n; i++){
        cout << arr[i] <<" ";
    }

    return 0;
}
Output:
1 2 5
  • Time Complexity: O(n) where n is the number of elements in the array.
  • Space Complexity: O(n) where n is the number of elements in the array.

Approach 3: Two Pointer Approach.

In this approach, we are not going to use any extra space to solve the problem instead we are going to use an in-place approach. Below are the steps to follow:
  • Use two pointers - one to iterate through the array and another to keep track of the position to overwrite.
  • Iterate through the array from the second element.
  • If the current element is different from the previous one, overwrite the next position with the current element.
  • The array up to the position of the second pointer will now contain elements without duplicates.
By completing the above steps all unique elements will move from the given vector (array) and then you can resize the vector up to the last overwrite position.

Note: We are starting the iteration from 1 because the element at position 0 is always unique and it does not require any replacement.

Example Code: Below is the C++ code implementation for the above approach.
//C++ code to remove duplicate elements from the array
//In-place approach
#include <bits/stdc++.h>
using namespace std;

int removeDuplicatesInPlace(vector<int>& arr) {

    int writeIndex = 1; // Position to overwrite

    for (size_t i = 1; i < arr.size(); ++i) {
        if (arr[i] != arr[i - 1]) {
            arr[writeIndex++] = arr[i];
        }
    }

    // Resize the array to the size of unique elements
    arr.resize(writeIndex);
    return arr.size();
}

int main(){
    vector<int> arr = {0, 1, 1, 2, 2, 2, 2, 4, 5, 5};

    int n = removeDuplicatesInPlace(arr);

    for(int i = 0; i < n; i++){
        cout << arr[i] <<" ";
    }

    return 0;
}
Output:
0 1 2 4 5
  • Time Complexity: O(n) where n is the number of elements in the array.
  • Space Complexity: O(1) in-place modification is performed so no extra space is required.
So these are the three different approaches to removing duplicate elements from a sorted array. 

Access Specifiers in C++.

In C++, Access Specifiers or Access Modifiers are keywords used to control the visibility and accessibility of class members (data members and member functions) from outside the class. They are used to implement Data-Hiding concepts in Object Oriented Programming


Let's understand them with one real-life example. Imagine you have a remote-controlled car that has three buttons to perform different things:

  • Public Buttons: These are the big, colorful buttons on the top that anyone can press. They make the car go forward, backward, left, and right. These are public actions that anyone can control.
  • Private Buttons: Inside the remote, some special buttons are hidden. These buttons do things like changing the car's battery or adjusting its internal settings. We don't want just anyone messing with these buttons because it might break the car. Only the person who owns the remote (the car itself) knows about these buttons.
  • Protected Buttons: These are a bit like private buttons, but they can be used by a close friend who has a special key. This friend knows a bit more about how the car works and can use these buttons to customize the car safely.
Similarly, in the programming world, there are three access specifiers: 
  • public. 
  • private.
  • protected.

Let's understand each specifier one by one in detail:

1. Public: Members declared as public are accessible from any part of the program. They have no restrictions on access. Data members and Member Functions which is declared as public can be accessible by different class or function as well. They form the interface of the class, and users can interact with these members freely.

Example Code:

// C++ example to show public access specifier
#include<iostream>
using namespace std;

// define class
class Area{
    // access specifier
    public: 
    int length;
    int breadth;

    int calArea(){
        return length *breadth;
    }
};

int main(){
    Area obj;

    obj.breadth = 5;
    obj.length = 10;

    cout<< "Breadth: " << obj.breadth << endl;
    cout<< "Length: " << obj.length << endl;
    cout << "Aread of Rectangle: " << obj.calArea() << endl;

    return 0;
}
Output:
Breadth: 5
Length: 10
Aread of Rectangle: 50

In the above example, the data member length and breadth are declared as public so we can access and modify their value outside the class.

2. Private: Members declared as private are only accessible within the same class. They are not accessible from outside the class. They are used to encapsulate the internal implementation details of the class.

Example Code:
// C++ example to show private access specifier
#include<iostream>
using namespace std;

// define class
class Area{
    // access specifier
    private: 
    int length;
    int breadth;

    int calArea(){
        return length * breadth;
    }
};

int main(){
    Area obj;
    
    obj.breadth = 5; // Error: privateVar is not accessible
    obj.length = 10; // Error: privateVar is not accessible

    cout<< "Breadth: " << obj.breadth << endl;
    cout<< "Length: " << obj.length << endl;
    cout << "Aread of Rectangle: " << obj.calArea() << endl;

    return 0;
}
Output:
output screenshot for private access specifier

In this above example, the data members and member function are declared as private so we cannot access them outside the class and get the above error.

3. Protected: Members declared as protected are similar to private members but have one additional feature: they can be accessed in the derived classes. They are not accessible from outside the class. They allow derived classes to access certain members while still restricting access to the external world.

Example Code:
//C++ example for protected access specifier
#include <iostream>
using namespace std;

// Base class
class Vehicle {
protected:
    int speed;

public:
    Vehicle() : speed(0) {}

    void setSpeed(int s) {
        speed = s;
        cout << "Setting speed to " << speed << " km/h\n";
    }
};

// Derived class
class Car : public Vehicle {
public:
    void showSpeed() {
        // Derived class can access the protected member 'speed' of the base class
        cout << "Current speed of the car: " << speed << " km/h\n";
    }

    void accelerate() {
        // Derived class can modify the protected member 'speed' of the base class
        speed += 10;
        cout << "Accelerating! New speed: " << speed << " km/h\n";
    }
};

int main() {
    Car myCar;

    // Accessing the public function of the base class
    myCar.setSpeed(60);

    // Accessing the public function of the derived class
    myCar.showSpeed();

    // Accessing a function of the derived class that modifies the protected member of the base class
    myCar.accelerate();
    myCar.showSpeed();

    return 0;
}
Output:
Setting speed to 60 km/h
Current speed of the car: 60 km/h
Accelerating! New speed: 70 km/h
Current speed of the car: 70 km/h

In this example, the Vehicle is the base class, and it has a protected member speed. Car is a derived class from Vehicle. The derived class Car can access and modify the protected member speed of the base class Vehicle.

So I hope you understand the working and use of Access specifiers and their contribution to the principles of encapsulation and data hiding in object-oriented programming.

Classes and Objects in C++.

C++ is an object-oriented programming language, and one of its key features is the ability to create and use classes and objects. Classes and Objects in C++ are the basic building blocks for Object Oriented Programming. In this article, we are going to learn the concept of classes and objects in detail with real-life examples.


What is a Class?

At its core, a class is a blueprint for creating objects. It encapsulates data (attributes) and behaviors (methods), providing a logical structure for organizing and modeling real-world entities. 

Data Members (Attributes): Data members define the attributes of a class, representing its state. They can include fundamental types or other user-defined types.(alert-passed)
Member Functions (Methods): Member functions define the behaviors of a class. They encapsulate operations that can be performed on the class's data.(alert-passed)

SyntaxIn C++, declaring a class involves using the class keyword, followed by the class name and a set of curly braces containing class members.

class ClassName {
    Access Specifier:

    Data Member;

    Member Function();
};


Example: Let's understand with an example, a Car can be represented as a class. A Car class can have attributes (data members) that define its state and behaviors (member functions) that represent its actions. 

class Car {
public: //Access Specifier
    // Attributes
    string brand;
    string model;
    int year;
    bool engineRunning;

    // Member Function to Start the Engine
    void startEngine() {
        if (!engineRunning) {
            cout << "Starting the engine...\n";
            engineRunning = true;
        } else {
            cout << "The engine is already running.\n";
        }
    }
};

What is an Object?

Objects are instances of classes, representing tangible entities in a program. They encapsulate data and behaviors defined by the class, forming the building blocks of C++ applications.

Syntax: Creating an object involves specifying the class name followed by the object name.
ClassName objectName;  // Creating an object

The data member and member function of the class can be accessed using the dot operator with the object name. For example, if your object name is myCar and you want to access the member function startEngine() then you have to write myCar.startEngine() to access that particular function.

Access Specifiers in C++.

Access specifiers control the visibility of class members (data member and member function) from different parts of the program. They are keywords used to define the accessibility or visibility of class members (data members and member functions). 

There are three access specifiers in C++:
  • Public: Members declared as public are accessible from any part of the program. They have no restrictions on access.
  • Private: Members declared as private are only accessible within the same class. They are not accessible from outside the class.
  • Protected: Members declared as protected are similar to private members but have one additional feature: they can be accessed in the derived classes. They are not accessible from outside the class.
Example:
//Access Specifier Example
class AccessExample {
public:
    int publicVar;

private:
    int privateVar;

protected:
    int protectedVar;

public:
    void displayValues() {
        cout << "Public: " << publicVar << "\n";
        cout << "Private: " << privateVar << "\n"; //Err: private is not accessible
        cout << "Protected: " << protectedVar << "\n";
    }
};

Access specifiers provide control over the visibility and accessibility of the class members, contributing to the principles of encapsulation and data hiding in object-oriented programming.

Constructors.

In C++, a constructor is a special member function that is automatically called when an object is created. It has the same name as the class and does not have any return type. The purpose of a constructor is to initialize the object's data members or perform other setup operations when an object is created.

There are two main types of constructors:

Default Constructor:
  • A default constructor is a constructor that takes no parameters.
  • If a class does not have any constructor defined, the compiler automatically generates a default constructor.
  • It initializes the data members with default values (zero or null, depending on the data type).

Parameterized Constructor:
  • A parameterized constructor is a constructor that takes parameters.
  • It allows you to initialize the object with specific values when it is created.
Example:
#include <iostream>

class Car {
private:
    std::string brand;
    int year;

public:
    // Default Constructor
    Car() {
        brand = "Unknown";
        year = 0;
    }

    // Parameterized Constructor
    Car(std::string carBrand, int carYear) {
        brand = carBrand;
        year = carYear;
    }

    void displayInfo() {
        std::cout << "Brand: " << brand << "\n";
        std::cout << "Year: " << year << "\n";
    }
};

int main() {
    // Using Default Constructor
    Car defaultCar;
    defaultCar.displayInfo();

    // Using Parameterized Constructor
    Car customCar("Toyota", 2022);
    customCar.displayInfo();

    return 0;
}
Output:
Brand: Unknown
Year: 0
Brand: Toyota
Year: 2022

In this example, the Car class has a default constructor that initializes the brand and year with default values. It also has a parameterized constructor that allows you to specify the brand and year when creating an object.

Destructor.

In C++, a destructor is a special member function of a class that is automatically called when an object goes out of scope or is explicitly deleted using the delete keyword. The purpose of a destructor is to release resources or perform cleanup operations before the object is destroyed.

The destructor has the same name as the class, preceded by a tilde (~). Unlike constructors, destructors do not take any parameters, and a class can have only one destructor.

Example:
#include <iostream>

class MyClass {
public:
    // Constructor
    MyClass() {
        std::cout << "Constructor called\n";
    }

    // Destructor
    ~MyClass() {
        std::cout << "Destructor called\n";
    }
};

int main() {
    // Object creation
    MyClass obj; // Constructor called

    // Object goes out of scope
    // Destructor is automatically called here

    return 0;
}
Output:
Constructor called
Destructor called

I hope you understand the basic workings of classes and objects in Object Oriented Programming. There are several key points that you can keep in mind when you are working with classes. 
  • Use access specifiers (public, private, protected) to control the visibility of class members.
  • Always define a constructor and, if needed, a destructor to manage the object's lifecycle.
  • Ensure that all class members are properly initialized, either through default values, member initialization lists, or in the constructor body.
  • Consider making functions const-correct when they do not modify the object's state.
  • Access static members using the class name, not an instance.
  • Prefer composition over inheritance to achieve polymorphic behavior.

DON'T MISS

Tech News
© all rights reserved
made with by AlgoLesson