Blog

  • C++ Copy Constructor

    Copy Constructor

    The copy constructor is a constructor that creates an object by initializing it with an object of the same class which has been created previously. The copy constructor is used to −

    • Initialize one object from another of the same type.
    • Copy an object to pass it as an argument to a function.
    • Copy an object to return it from a function.

    If a copy constructor is not defined in a class, the compiler itself defines one.If the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor.

    Syntax

    The most common form of copy constructor is shown here −

    classname(const classname &obj){// body of constructor}

    Here, obj is a reference to an object that is being used to initialize another object.

    Example of Copy Constructor

    The following example demonstrates the use of the copy constructor:

    #include <iostream>usingnamespace std;classLine{public:intgetLength(void);Line(int len );// simple constructorLine(const Line &obj);// copy constructor~Line();// destructorprivate:int*ptr;};// Member functions definitions including constructorLine::Line(int len){
       cout <<"Normal constructor allocating ptr"<< endl;// allocate memory for the pointer;
       ptr =newint;*ptr = len;}Line::Line(const Line &obj){
       cout <<"Copy constructor allocating ptr."<< endl;
       ptr =newint;*ptr =*obj.ptr;// copy the value}Line::~Line(void){
       cout <<"Freeing memory!"<< endl;delete ptr;}intLine::getLength(void){return*ptr;}voiddisplay(Line obj){
       cout <<"Length of line : "<< obj.getLength()<<endl;}// Main function for the programintmain(){
       Line line(10);display(line);return0;}

    When the above code is compiled and executed, it produces the following result −

    Normal constructor allocating ptr
    Copy constructor allocating ptr.
    Length of line : 10
    Freeing memory!
    Freeing memory!
    

    Copy Constructor to Create New Object

    You can create a new object by using the existing object through the concept of a copy constructor.

    In the following example, the copy constructor is used to create a new object as a copy of an existing object.

    Example

    Let us see the same example but with a small change to create another object using existing object of the same type −

    #include <iostream>usingnamespace std;classLine{public:intgetLength(void);Line(int len );// simple constructorLine(const Line &obj);// copy constructor~Line();// destructorprivate:int*ptr;};// Member functions definitions including constructorLine::Line(int len){
       cout <<"Normal constructor allocating ptr"<< endl;// allocate memory for the pointer;
       ptr =newint;*ptr = len;}Line::Line(const Line &obj){
       cout <<"Copy constructor allocating ptr."<< endl;
       ptr =newint;*ptr =*obj.ptr;// copy the value}Line::~Line(void){
       cout <<"Freeing memory!"<< endl;delete ptr;}intLine::getLength(void){return*ptr;}voiddisplay(Line obj){
       cout <<"Length of line : "<< obj.getLength()<<endl;}// Main function for the programintmain(){
    
       Line line1(10);
    
       Line line2 = line1;// This also calls copy constructordisplay(line1);display(line2);return0;}

    When the above code is compiled and executed, it produces the following result −

    Normal constructor allocating ptr
    Copy constructor allocating ptr.
    Copy constructor allocating ptr.
    Length of line : 10
    Freeing memory!
    Copy constructor allocating ptr.
    Length of line : 10
    Freeing memory!
    Freeing memory!
    Freeing memory!
    

    Implicit vs. Explicit Copy Constructors

    In C++, there are two types of Copy Constructors that’s Implicit and Explicit. Here we will discuss the difference between these two.

    Implicit Copy Constructor

    If the user doesn’t define their own copy constructor, then the compiler automatically provides an implicit copy constructor. It performs a shallow copy of the object, which means that it copies the values of each member of the object to the new object.

    When is the Implicit Copy Constructor called?

    • When a user passes an object by value to a function.
    • When the user returns an object by value from a function.
    • When the user initializes an object with another object of the same type (copy initialization).

    Explicit (User-Defined) Copy Constructor

    It is the user-defined constructor. This gives you access to customize the copy behavior like creating a deep copy instead of the default shallow copy.

    Example

    Here is the example for both explicit and implicit copy constructors in C++:

    #include <iostream>usingnamespace std;classMyClass{private:int value;public:// ConstructorMyClass(int v):value(v){}// Explicit Copy ConstructorMyClass(const MyClass& other):value(other.value){
        cout <<"Explicit Copy Constructor called"<< endl;}voiddisplay()const{ cout <<"Value: "<< value << endl;}};voidprocessValue(MyClass obj){// Implicit copy constructor will be called here
      obj.display();}intmain(){
      MyClass obj1(10);// Constructor called
      MyClass obj2 = obj1;// Explicit copy constructor called
      obj1.display();
      obj2.display();processValue(obj1);// Implicit copy constructor calledreturn0;}

    When the above code is compiled and executed, it produces the following result −

    Explicit Copy Constructor called
    Value: 10
    Value: 10
    Explicit Copy Constructor called
    Value: 10
    

    Rule of Three/Five

    The Rule of Three and Rule of Five suggest while defining a copy constructor (ClassName(const ClassName& other)) you should also define:

    The Rule of Three and Rule of Five suggest while defining a copy constructor (ClassName(const ClassName& other)) you should also define:

    • Rule of Three:
      • destructor (~ClassName()).
      • And copy assignment operator (ClassName& operator=(const ClassName& other)), to ensure that memory is correctly managed.
    • Rule of Five:
      • move constructor (ClassName(ClassName&& other)).
      • move assignment operator (ClassName& operator=(ClassName&& other))”. 

    These special member functions are necessary for the proper management of dynamic memory and other and other resources like file handling or network connections in a class.

    Deep Copy vs. Shallow Copy

    In C++, deep copy and shallow copy are different ways of copying objects and they are important when a class involves dynamic memory management.

    1. Shallow Copy

    It occurs when an object is copied in such a way that both original and copied objects share the same resources. This means that the copy constructor or copy assignment operator simply copies the values of data members (like pointers), without allocating new memory or making independent copies of the resources.

    Example

    #include <iostream>usingnamespace std;classMyClass{private:int* data;// Pointer to an integerpublic:// ConstructorMyClass(int value){
        data =newint(value);// Allocate memory}// Shallow Copy ConstructorMyClass(const MyClass& other){
        data = other.data;// Copy pointer only}// Destructor~MyClass(){delete data;// Free memory}// Display the valuevoidshowData()const{ cout <<"Data: "<<*data << endl;}};intmain(){
      MyClass obj1(42);// Create an object
      MyClass obj2 = obj1;// Use shallow copy constructor
    
      obj1.showData();
      obj2.showData();return0;}

    When the above code is compiled and executed, it produces the following result −

    Data: 42
    Data: 42
    free(): double free detected in tcache 2
    

    2. Deep Copy

    It occurs when an object is copied by allocating new memory for its own copy of the resources, making sure that the original and copied object is completely independent. Avoids double-free errors or dangling pointers.

    Example

    #include <iostream>usingnamespace std;classMyClass{private:int* data;// Pointer to an integerpublic:// Constructor: Dynamically allocate memory // and initialize with valueMyClass(int value){ data =newint(value);}// Deep Copy Constructor// Allocates new memory and copies the valueMyClass(const MyClass& other){ data =newint(*other.data);}// Destructor to clean up memory~MyClass(){delete data;}// Display the valuevoidshowData()const{ cout <<"Data: "<<*data << endl;}};intmain(){
      MyClass obj1(42);// Create an object
      MyClass obj2 = obj1;// Use deep copy constructor
    
      obj1.showData();// Display data from obj1
      obj2.showData();// Display data from obj2return0;}

    When the above code is compiled and executed, it produces the following result −

    Data: 42
    Data: 42
  • C++ – Parameterized Constructors

    In C++, constructors are special member functions, which are called automatically, when an object is created. There are two main types of constructors: default constructors and parameterized constructors.

    A default constructor is a constructor that does not take any parameters or has default values for all parameters.

    whereas a parameterized constructor is a constructor, which takes one or more parameters and is used to initialize an object with specific values passed when an object is created.

    In this chapter, we will learn only about the Parameterized Constructor.

    C++ Parameterized Constructors

    C++ parameterized constructor is a constructor, which accepts one or more arguments or parameters, to initialize an object with specific values, when created. Unlike the default constructor, which takes no arguments, a parameterized constructor takes one or more arguments.

    Syntax

    Here is the following syntax for declaring a parameterized constructor:

    ClassName(parameters){// Initialization code}

    Example of Parameterized Constructor

    Here is the following example of a parameterized constructor in C++:

    #include <iostream>usingnamespace std;classMyClass{public:int a, b;// Parameterized constructor with two argumentsMyClass(int x,int y){
             a = x;// Initialize 'a' with the value of 'x'
             b = y;// Initialize 'b' with the value of 'y'
             cout <<"Parameterized constructor called"<< endl;}// Method to display values of 'a' and 'b'voiddisplay(){
             cout <<"a: "<< a <<", b: "<< b << endl;}};intmain(){
       MyClass obj1(10,20);// Calls the parameterized constructor with 10 and 20
       obj1.display();// Output: a: 10, b: 20return0;}

    Output

    Parameterized constructor called
    a: 10, b: 20
    

    Explanation

    • First defined the class named MyClass, with two public data members a and b of int type.
    • Then a parameterized constructor, MyClass(int x, int y), takes two arguments (int x, int y) and initializes them a and b with values passed when the object is created.
    • Now when the MyClass obj1(10, 20) is called, the parameterized constructor will be invoked.
    • and display() method will print the values of a and b.

    Multiple Parameterized Constructors (Constructor Overloading)

    Constructor overloading or multiple parameterized constructors in C++, is a concept, which allows users to define multiple constructors in the same class with different parameter lists, where each constructor can initialize the object differently depending on the arguments passed while creating an object.

    Key points

    • Same Constructor Name − All overloaded constructors must have the same name as the class.
    • Different Parameters − Constructors must have a different number or types of parameters.
    • Flexibility − Constructor overloading also gives flexibility during object initialization by allowing the same class to be instantiated in various ways.

    Syntax

    Here is the following syntax for multiple parameterised constructor:

    classClassName{public:// Default constructor (no parameters)ClassName(){// Initialization code}// Parameterized constructor with one parameterClassName(Type1 param1){// Initialization code using param1}// Parameterized constructor with two parametersClassName(Type1 param1, Type2 param2){// Initialization code using param1 and param2}// Parameterized constructor with three parametersClassName(Type1 param1, Type2 param2, Type3 param3){// Initialization code using param1, param2, and param3}};

    Parameterized Constructors with Default Arguments

    A parameterized constructor with default arguments is a constructor, which allows a user to provide default values for one or more parameters, which means you can either pass values while creating the object or let the constructor use the default values for the missing parameters.

    Syntax

    Here is the following syntax for a parameterized constructor with default arguments:

    classClassName{public:// Constructor with default argumentsClassName(type1 param1 = default_value1, type2 param2 = default_value2,...){// Constructor implementation}};

    Advantages of Using Parameterized Constructors

    Parameterized constructors offer various benefits, which make object initialization more flexible, clean, and efficient. Below we have discussed some of the key advantages.

    • It allows flexible object initialization with simplified code, improving readability and maintainability.
    • It prevents Object Creation with Invalid Data, where it allows valid data only.
    • It reduces the need for setter functions and supports constructor overloading.
    • It also provides better memeory management (with Dynamic Memory Allocation), enforces Default Values for Missing Arguments, and overall improves code performance.
  • C++ – Default Constructors

    Constructors are functions of a class that are executed when new objects of the class are created. The constructors have the same name as the class and no return type, not even void. They are primarily useful for providing initial values for variables of the class. The two main types of constructors are default constructors and parameterized constructors.

    Default Constructors

    C++ default constructors do not take any parameters. If a default constructor is not provided by the programmer explicitly, then the compiler provides a implicit default constructor. In that case, the default values of the variables are 0.

    Syntax

    Here is the following syntax for a default constructor:

    classMyClass{public:MyClass(){// Default constructor body}};

    Example of Default Constructor

    A program demonstrating default constructors is given as follows:

    #include <iostream>usingnamespace std;classDemoDC{private:int num1, num2 ;public:DemoDC(){
             num1 =10;
             num2 =20;}voiddisplay(){
          cout<<"num1 = "<< num1 <<endl;
          cout<<"num2 = "<< num2 <<endl;}};intmain(){
       DemoDC obj;
       obj.display();return0;}

    Output

    num1 = 10
    num2 = 20
    

    Explanation

    • Here first created the Object of type DemoDC(), where the default constructor automatically invoked.
    • It initializes the class members num1 and num2 with the values 10 and 20.
    • Then the display() method prints these values.

    Implicit vs Explicit Default Constructors

    In object-oriented programming (OOP), depending on how a default constructor is declared, it can be divided into two categories, implicit and explicit.

    1. Implicit Default Constructor

    An implicit default constructor is a constructor that is automatically called by the complier when an object is created, it may also be invoked if the user passes arguments that would be convertible into the constructor’s parameters.

    Syntax

    classMyClass{int x;double y;};intmain(){
       MyClass obj;// Implicit default constructor is called}

    2. Explicit Default Constructor

    An explicit default constructor is the one where the constructor is not allowed to be called implicitly by the compiler when performing automatic type conversions or copy-initialization. In other words, the user can only call directly when providing a matching argument.

    Syntax

    classClassName{public:explicitClassName(int x =10);// Explicit constructor};

    Default Constructor vs Parameterized Constructor

    A default constructor is a constructor, which takes no parameter or has all its parameters set to default values.

    Whereas a parameterized constructor is a constructor, which takes one or more arguments. It allows users to pass values during the creation of an object, which is further used for the initialization of an object.

    In this tutorial, we will basically learn about the default constructor.

    Syntax

    Here is the following Syntax for the Default constructor.

    classClassName{public:// Default constructorClassName(){// Initialization or setup code}};

    Here is the following example for the Default constructor.

    Explanation

    • In this example, first, we created the class named DemoDC.
    • In class, two private member variables num1 and num2 of type int are declared.
    • then a default constructor is defined for the DemoDC class. Where this constructor is automatically called when an object of the class is created.
    • In this constructor num1 and num2 are initialized to 100 and 20 respectively.
    • In int main(), an object of the class DemoDC is created, which triggers the default constructor DemoDC().
    • And obj.display() displays the values of num1 and num2.

    When Default Constructor Called?

    A default constructor is called in various situations, mainly when an object is created without arguments. Here we will discuss more situations where the default constructor is invoked.

    • When an Object is created without arguments.
    • When a class does not explicitly define any constructors.
    • In derived classes, if the base class has a default constructor.
    • When dynamically allocating an object.

    Overloading the Default Constructor

    In C++, overloading the default constructor is said to create multiple constructors within a class, where each constructor has a different parameter list, allowing for different ways of initializing objects.

    Example

    Here is the following example for Overloading the default Constructor in C++.

    #include <iostream>usingnamespace std;classMyClass{public:int a, b;// Default constructor (no arguments)MyClass():a(0),b(0){
             cout <<"Default constructor called"<< endl;}// Overloaded constructor with one argumentMyClass(int x):a(x),b(0){
             cout <<"Overloaded constructor (1 argument) called"<< endl;}// Overloaded constructor with two argumentsMyClass(int x,int y):a(x),b(y){
             cout <<"Overloaded constructor (2 arguments) called"<< endl;}voiddisplay(){
             cout <<"a: "<< a <<", b: "<< b << endl;}};intmain(){
       MyClass obj1;// Calls default constructor
       MyClass obj2(10);// Calls overloaded constructor (1 argument)
       MyClass obj3(10,20);// Calls overloaded constructor (2 arguments)
    
       obj1.display();
       obj2.display();
       obj3.display();return0;}

    Output

    Default constructor called
    Overloaded constructor (1 argument) called
    Overloaded constructor (2 arguments) called
    a: 0, b: 0
    a: 10, b: 0
    a: 10, b: 20
    

    Explanation

    • Here, MyClass() is the default constructor, where initializing a and b to 0.
    • MyClass(int x) is the constructor with one argument, where initializing a and b to x and 0 respectively.
    • MyClass(int x, int y) is the constructor with two arguments, where initializing both a and b to x and y respectively.
  • C++ Class Constructor and Destructor

    The Class Constructor

    A class constructor is a special member function of a class that is executed whenever we create new objects of that class.

    A constructor will have exact same name as the class and it does not have any return type at all, not even void. Constructors can be very useful for setting initial values for certain member variables.

    Example

    Following example explains the concept of constructor −

    #include <iostream>usingnamespace std;classLine{public:voidsetLength(double len );doublegetLength(void);Line();// This is the constructorprivate:double length;};// Member functions definitions including constructorLine::Line(void){
       cout <<"Object is being created"<< endl;}voidLine::setLength(double len ){
       length = len;}doubleLine::getLength(void){return length;}// Main function for the programintmain(){
       Line line;// set line length
       line.setLength(6.0); 
       cout <<"Length of line : "<< line.getLength()<<endl;return0;}

    When the above code is compiled and executed, it produces the following result −

    Object is being created
    Length of line : 6
    

    Parameterized Constructor

    A default constructor does not have any parameter, but if you need, a constructor can have parameters. This helps you to assign initial value to an object at the time of its creation.

    Example

    The following example demonstrates the use of parameterized constructors:

    #include <iostream>usingnamespace std;classLine{public:voidsetLength(double len );doublegetLength(void);Line(double len);// This is the constructorprivate:double length;};// Member functions definitions including constructorLine::Line(double len){
       cout <<"Object is being created, length = "<< len << endl;
       length = len;}voidLine::setLength(double len ){
       length = len;}doubleLine::getLength(void){return length;}// Main function for the programintmain(){
       Line line(10.0);// get initially set length.
       cout <<"Length of line : "<< line.getLength()<<endl;// set line length again
       line.setLength(6.0); 
       cout <<"Length of line : "<< line.getLength()<<endl;return0;}

    When the above code is compiled and executed, it produces the following result −

    Object is being created, length = 10
    Length of line : 10
    Length of line : 6
    

    Using Initialization Lists to Initialize Fields

    In case of parameterized constructor, you can use following syntax to initialize the fields −

    Line::Line(double len):length(len){
       cout <<"Object is being created, length = "<< len << endl;}

    Above syntax is equal to the following syntax −

    Line::Line(double len){
       cout <<"Object is being created, length = "<< len << endl;
       length = len;}

    If for a class C, you have multiple fields X, Y, Z, etc., to be initialized, then use can use same syntax and separate the fields by comma as follows −

    C::C(double a,double b,double c):X(a),Y(b),Z(c){....}

    The Class Destructor

    destructor is a special member function of a class that is executed whenever an object of it’s class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class.

    A destructor will have exact same name as the class prefixed with a tilde (~) and it can neither return a value nor can it take any parameters. Destructor can be very useful for releasing resources before coming out of the program like closing files, releasing memories etc.

    Example

    Following example explains the concept of destructor −

    #include <iostream>usingnamespace std;classLine{public:voidsetLength(double len );doublegetLength(void);Line();// This is the constructor declaration~Line();// This is the destructor: declarationprivate:double length;};// Member functions definitions including constructorLine::Line(void){
       cout <<"Object is being created"<< endl;}Line::~Line(void){
       cout <<"Object is being deleted"<< endl;}voidLine::setLength(double len ){
       length = len;}doubleLine::getLength(void){return length;}// Main function for the programintmain(){
       Line line;// set line length
       line.setLength(6.0); 
       cout <<"Length of line : "<< line.getLength()<<endl;return0;}

    When the above code is compiled and executed, it produces the following result −

    Object is being created
    Length of line : 6
    Object is being deleted
  • Pointer to C++ Classes

    Pointer to Classes

    A pointer to a C++ class is done exactly the same way as a pointer to a structure and to access members of a pointer to a class you use the member access operator -> operator, just as you do with pointers to structures. Also as with all pointers, you must initialize the pointer before using it.

    Example of Pointer to Classes

    Let us try the following example to understand the concept of pointer to a class −

    #include <iostream>usingnamespace std;classBox{public:// Constructor definitionBox(double l =2.0,double b =2.0,double h =2.0){
             cout <<"Constructor called."<< endl;
             length = l;
             breadth = b;
             height = h;}doubleVolume(){return length * breadth * height;}private:double length;// Length of a boxdouble breadth;// Breadth of a boxdouble height;// Height of a box};intmain(void){
       Box Box1(3.3,1.2,1.5);// Declare box1
       Box Box2(8.5,6.0,2.0);// Declare box2
       Box *ptrBox;// Declare pointer to a class.// Save the address of first object
       ptrBox =&Box1;// Now try to access a member using member access operator
       cout <<"Volume of Box1: "<< ptrBox->Volume()<< endl;// Save the address of second object
       ptrBox =&Box2;// Now try to access a member using member access operator
       cout <<"Volume of Box2: "<< ptrBox->Volume()<< endl;return0;}

    When the above code is compiled and executed, it produces the following result −

    Constructor called.
    Constructor called.
    Volume of Box1: 5.94
    Volume of Box2: 102
  • C++ Friend Functions

    C++ Friend Function

    A friend function of a class is defined outside that class scope but it has the right to access all private and protected members of the class. Even though the prototypes for friend functions appear in the class definition, friends are not member functions.

    A friend can be a function, function template, member function, or a class or class template, in which case the entire class and all of its members are friends.

    Declaring Friend Function

    To declare a function as a friend of a class, precede the function prototype in the class definition with the keyword friend as follows

    Syntax

    class Box {
       double width;
       
       public:
          double length;
          friend void printWidth( Box box );
          void setWidth( double wid );
    };
    

    To declare all member functions of class ClassTwo as friends of class ClassOne, place a following declaration in the definition of class ClassOne −

    friend class ClassTwo;
    

    Example of Friend Function

    Here is the following code for Function Friend in C++:

    #include <iostream>usingnamespace std;classBox{double width;public:friendvoidprintWidth( Box box );voidsetWidth(double wid );};// Member function definitionvoidBox::setWidth(double wid ){
       width = wid;}// Note: printWidth() is not a member function of any class.voidprintWidth( Box box ){/* Because printWidth() is a friend of Box, it can
       directly access any member of this class */
       cout <<"Width of box : "<< box.width <<endl;}// Main function for the programintmain(){
       Box box;// set box width without member function
       box.setWidth(10.0);// Use friend function to print the wdith.printWidth( box );return0;}

    When the above code is compiled and executed, it produces the following result −

    Width of box : 10
    

    Accessing Private and Protected Members

    The private and protected members of a class are not accessible outside of the class. Still, if you want to access them, you can use the friend function. The friend function provides the ability to directly access the class’s private and protected members.

    Example

    The following example demonstrates accessing private and protected members of a class using the friend function:

    #include <iostream>usingnamespace std;classClassName{private:int privateData;// Private memberprotected:int protectedData;// Protected memberpublic:ClassName():privateData(0),protectedData(0){}// Declare a friend functionfriendvoidfriendFunction(ClassName& obj);};// Friend function definitionvoidfriendFunction(ClassName& obj){
      obj.privateData =42;// Access private member
      obj.protectedData =24;// Access protected member
      cout <<"Private Data: "<< obj.privateData << endl;
      cout <<"Protected Data: "<< obj.protectedData << endl;}intmain(){
      ClassName obj;friendFunction(obj);// Call the friend functionreturn0;}

    When the above code is compiled and executed, it produces the following result −

    Private Data: 42
    Protected Data: 24
    

    Friend Function vs Member Function

    In C++, both friend functions and member functions are used to access and manipulate the data of a class, but still, they have significant differences in their scope and usage.

    Friend Function

    A friend Function is a non-member function that is declared inside a class using the “friend” keyword, it has special access to the class’s private and protected members. Since it’s not a member it is not bound to a specific object, can’t overloaded based on objects, not use this pointer, and cannot be inherited by derived classes. They are defined outside the class but declared inside it.

    Member function

    Whereas the member function is defined within the class and operates using this pointer. It can access all members of the class (private, protected, and public), and as it is tied to class objects, it can be overloaded and inherited by derived classes.

    Friend Classes

    In C++, a friend class is a class that gives access to private and protected members of another class. When a class declares another class as a friend, the second class (the friend) can directly access the private and protected members of the first class.

    This concept is similar to friend functions, but here the friend is an entire class rather than a specific function.

    Syntax

    Here is the following syntax for the friend class in C++:


    class ClassB; // Forward declaration of ClassB class ClassA { private: int dataA; public: // Declare ClassB as a friend of ClassA friend class ClassB; }; Example The following example demonstrates the example of a friend class in C++: #include <iostream> using namespace std; class ClassB; // Forward declaration of ClassB class ClassA { private: int dataA; public: ClassA() : dataA(42) {} // Initialize dataA with a value // Declare ClassB as a friend of ClassA friend class ClassB; }; class ClassB { public: void showDataFromA(const ClassA& objA) { // Access private member of ClassA cout << “Data from ClassA: ” << objA.dataA << endl; } }; int main() { ClassA objA; ClassB objB; // Use ClassB to access ClassA’s private data objB.showDataFromA(objA); return 0; }

  • C++ this Pointer

    this Pointer

    Every object in C++ has access to its own address through an important pointer called this pointer. The this pointer is an implicit parameter for all member functions. Therefore, inside a member function, this may be used to refer to the invoking object.

    Friend functions do not have a this pointer because friends are not members of a class. Only member functions have this pointer.

    Example of this Pointer

    Let us try the following example to understand the concept of this pointer −

    #include <iostream>usingnamespace std;classBox{public:// Constructor definitionBox(double l =2.0,double b =2.0,double h =2.0){
             cout <<"Constructor called."<< endl;
             length = l;
             breadth = b;
             height = h;}doubleVolume(){return length * breadth * height;}intcompare(Box box){returnthis->Volume()> box.Volume();}private:double length;// Length of a boxdouble breadth;// Breadth of a boxdouble height;// Height of a box};intmain(void){
       Box Box1(3.3,1.2,1.5);// Declare box1
       Box Box2(8.5,6.0,2.0);// Declare box2if(Box1.compare(Box2)){
          cout <<"Box2 is smaller than Box1"<<endl;}else{
          cout <<"Box2 is equal to or larger than Box1"<<endl;}return0;}

    When the above code is compiled and executed, it produces the following result −

    Constructor called.
    Constructor called.
    Box2 is equal to or larger than Box1
    

    Return Calling Object’s Reference Using this Pointer

    To implement chain function calls, you need the reference of a calling object. You can use the “this” pointer to return the reference of the calling object.

    Syntax

    Here is the syntax:

    Test&Test::func(){return*this;}

    Example

    The following example demonstrates how you can return the reference to the calling object:

    #include <iostream>usingnamespace std;classCoordinates{private:int latitude;int longitude;public:Coordinates(int lat =0,int lon =0){this->latitude = lat;this->longitude = lon;}
    
      Coordinates&setLatitude(int lat){
        latitude = lat;return*this;}
    
      Coordinates&setLongitude(int lon){
        longitude = lon;return*this;}voiddisplay()const{
        cout <<"Latitude = "<< latitude <<", Longitude = "<< longitude << endl;}};intmain(){
      Coordinates location(15,30);// Chained function calls modifying the same object
      location.setLatitude(40).setLongitude(70);
    
      location.display();return0;}

    When the above code is compiled and executed, it produces the following result −

    Latitude = 40, Longitude = 70
    

    Characteristics of the “this” Pointer

    • The “this” pointer refers to the current instance of the object, where it allows the member function to access the object’s attributes and methods.
    • The “this” pointer is implicitly passed to all non-static member functions, where you don’t need to explicitly write this in code.
    • this points to the memory location of the current object.
    • If there is a name conflict between a parameter and a member variable, this can be used to differentiate the member variable from the local parameter.
    • the “this” pointer is constant (const), meaning it cannot be modified.
    • Since this is a pointer, it can be dereferenced to access the current object.

    this Pointer in Const Member Functions Vs Static Member Functions

    In const member functions, this pointer is a pointer to a constant object (const MyClass*), where the object’s members cannot be modified within the function, resulting in an object remaining unchanged when calling const functions.

    Whereas static member functions don’t have this pointer because they are not associated with any specific instance of the class, they belong to the class itself and can only access static members or methods, as they do not operate on object-specific data.

    Example

    Here is the given example representing both with this pointer in the Const member function Vs static member function.

    #include <iostream>classMyClass{public:MyClass(int val):data(val){}// Const member function (has 'this' pointer, but it's a const pointer)voidprintData()const{
             std::cout <<"Data: "<< data << std::endl;// 'this' points to a const object// Uncommenting the next line will cause an error because 'this' is const// data = 10;  // Error: cannot modify 'data' in a const member function}// Static member function (no 'this' pointer, operates on class-level data)staticvoidshowMessage(){
             std::cout <<"This is a static function!"<< std::endl;// Uncommenting the next line will cause an error because static functions can't access instance members// std::cout << "Data: " << data << std::endl;  // Error: 'data' is not accessible}private:int data;};intmain(){
       MyClass obj(5);// Calling const member function (can access 'this' as const)
       obj.printData();// Calling static member function (no 'this' pointer available)MyClass::showMessage();return0;}

    Output

    Data: 5
    This is a static function!
    

    Common Use Cases of this Pointer

    In C++, this pointer is a special pointer, which refers to the current instances of a class in non-static member functions.

    Here we will see its common use cases in the following.

    • this pointer helps in preventing self-assignment in assignment operators making sure that an object doesn’t assign itself to itself.
    • this pointer makes method chaining possible by returning the current object (usually through *this), allowing you to call several methods on the same object in a single line of code.
    • It allows for direct access to the object’s members within member functions.
    • It is important in copy constructors and assignment operators, as it helps return the current object during assignments.
    • it is also useful in Polymorphism, Inherited Classes, and Implement Fluent Interfaces, allowing smooth method chaining.

    Limitations of this Pointer

    The “this” pointer is a powerful feature in C++, but it has certain limitations and potential pitfalls that developers should keep in mind to prevent errors or unexpected behavior.

    • this pointer isn’t available in static member functions because static functions are tied to the class itself, not to any specific object.
    • It can help differentiate between member variables and local variables when their names overlap. However, if a local variable shadows a member variable, it can still lead to confusion or ambiguity.
    • this pointer always refers to the current object, but using it after the object is destroyed or while it’s being destroyed can cause undefined behavior.
    • When dealing with multiple inheritance, conflicts can occur if different base classes share members with identical names. This can make it unclear which member the this pointer is pointing to, leading to ambiguity.
    • Returning *this from a temporary object can be risky since it might leave behind a dangling reference, which could cause unexpected or undefined behavior.
  • C++ Inline Functions

    What is an Inline Function in C++

    C++ inline function is powerful concept that is commonly used with classes. If a function is inline, the compiler places a copy of the code of that function at each point where the function is called at compile time.

    Any change to an inline function could require all clients of the function to be recompiled because compiler would need to replace all the code once again otherwise it will continue with old functionality.

    Defining an Inline Function

    To define an inline function, place the keyword inline before the function name and define the function before any calls are made to the function. The compiler can ignore the inline qualifier in case defined function is more than a line.

    A function definition in a class definition is an inline function definition, even without the use of the inline specifier.

    Example

    Following is an example, which makes use of inline function to return max of two numbers −

    #include <iostream>usingnamespace std;inlineintMax(int x,int y){return(x > y)? x : y;}// Main function for the programintmain(){
       cout <<"Max (20,10): "<<Max(20,10)<< endl;
       cout <<"Max (0,200): "<<Max(0,200)<< endl;
       cout <<"Max (100,1010): "<<Max(100,1010)<< endl;return0;}

    When the above code is compiled and executed, it produces the following result −

    Max (20,10): 20
    Max (0,200): 200
    Max (100,1010): 1010
    

    Inline Function with Classes

    By default, all the functions that are defined inside a class are implicitly inline. If you want to explicitly define a function as inline, then you have to declare a function inside the class and write its definition outside the class. The inline keyword is used with the function definition that is outside of the class declaration.

    Example

    In the following example, we are defining an inline function with the class −

    #include <iostream>usingnamespace std;classNumber{private:int num1;int num2;public:// Function to set the valuesvoidsetValues(int a,int b);// Function to print the valuesvoidprintValues();// Inline function to add the two numbersinlineintaddNumbers();};// Member function definitionsvoidNumber::setValues(int a,int b){
        num1 = a;
        num2 = b;}voidNumber::printValues(){
        cout <<"Number 1: "<< num1 <<", Number 2: "<< num2 << endl;}// Inline function definitioninlineintNumber::addNumbers(){return num1 + num2;}intmain(){// Create an object
        Number n;// Set the values
        n.setValues(10,20);// Print the values
        n.printValues();// Add the numbers and print the resultint sum = n.addNumbers();
        cout <<"Sum of the numbers: "<< sum << endl;return0;}

    Advantages of Inline Function

    The following are the advantages of using inline function −

    • In the case of an inline function, the function call overhead does not occur.
    • The inline function saves the overhead of the push and pop variables on the stack, when the function is called.
    • An inline function saves the overhead of a return call from a function.
    • When an inline function is created, the compiler may perform context specific optimization on the body of the function. This kind of optimization is not performed for normal functions.
    • Using small inline functions may be useful for embedded systems, because inline can yield less code than the function call preamble and return.

    Disadvantages of Inline Function

    Some of the disadvantages of inline functions are as follows –

    • When we use an inline function, the size of the code is increased because the compiler replaces each function call with the inline function code.
    • Large sized code takes more memory and time to compiler the code.
    • The compilation process slows down because the compiler evaluates and replaces the function code at the place function calls.
    • In some of the cases, the program’s performance may slow down.
    • Based on the function code complexity, the compiler may ignore the inline keyword. Thus, the application of the inline function is limited.

    Some of the disadvantages of inline function are as follows −

  • C++ – Static Member Function

    Static Member Function

    Static Member Function in C++ is a special kind of function that belongs to the class itself rather than any specific object. A static keyword is used to define those functions. They can be directly called by using just the class name, without creating an instance of the class, which is an object.

    These are only accessible within the body of the class they are defined in, thus, implementing class-wide operations and certain security measures.

    Syntax

    Here is the given syntax for static member functions in C++:

    classClassName{public:static returnType functionName(parameters){// Function body}};

    Example of Static Member Function

    Here is the following example for the static member function:

    #include <iostream>usingnamespace std;classMyClass{public:staticvoiddisplayMessage(){
             cout <<"Hello, World!";}};intmain(){// Calling static member functionMyClass::displayMessage();return0;}

    Output

    Hello, World!
    

    Explanation

    • We define a class MyClass with a public static member function displayMessage().
    • The function simply prints “Hello, World!”.
    • In the main function, we directly call the function using the class name. Observe we haven’t created an instance of the class to call the function.

    Key features of Static Member Functions

    • There’s no access to this pointer with static functions as they’re not tied to an object instance.
    • These functions can be invoked using a class name.
    • They can only work with static members or other static functions of the class.

    When should static member functions be used?

    These are best suited for tasks that involve shared data and logic which is unrelated to specific objects. Here are some scenarios −

    • Maintaining counters, and handling global configurations.
    • In implementing interface methods that don’t require an object state.
    • Utility or helper functions like mathematical operations, data validations, etc.

    Example

    #include <iostream>usingnamespace std;classMathOperation{public:staticintsquare(int num){return num * num;}};intmain(){
       std::cout <<"Square of 2: "<<MathOperation::square(2)<<'\n';return0;}

    Output

    Square of 2: 4
  • Static Data Members in C++

    Static Data Members in C++

    In C++, a static data member is a class member or class-level variable, which is shared by all instances(objects) of that class. This is not like regular data members, which have separate copies for each object of the class, a static data member has only one copy for the entire class, which can be shared across all instances, which means that all objects of the class can access and modify the same value.

    Static Data Member Declaration

    This is the following syntax for declaring a static data member inside the class using a static keyword.

    classClassName{public:static dataType staticMemberName;};

    Static Data Member Initialization

    This is the following syntax for defining and initializing a static data member outside the class, which is done using ClassName:: scope resolution operator.

    dataType ClassName::staticMemberName = initialValue;

    Accessing Static Data Members

    Static data members can be accessed in two ways, that is −

    • Using the Class Name (Recommended)
    • Using an Object (Not Recommended)

    Here we will see the following differences between them and their syntax and examples.

    Accessing Static Data Members Using the Class Name

    This is the very common and preferred way of accessing a static data member, which is done by using the scope resolution operator ::

    Syntax

    Here is the following syntax for it.

    ClassName::staticDataMember;

    Accessing Static Data Members Using an Object

    You can also access a static data member using an object, but it’s generally not recommended because static members are independent of any specific object, and using an object can mislead it.

    Syntax

    Here is the following syntax for it.

    objectName.staticDataMember;

    Example

    Here is the following example of a static data member in C++.

    #include <iostream>#include <string>usingnamespace std;classBook{private:
          string title;// Title of the book
          string author;// Author of the bookpublic:// Static data member to track total books in the librarystaticint totalBooks;// Constructor to initialize the book's title and authorBook(string bookTitle, string bookAuthor){
          title = bookTitle;
          author = bookAuthor;
          totalBooks++;// Increment totalBooks every time a new book is created}// Static method to display the total number of booksstaticvoiddisplayTotalBooks(){
          cout <<"Total number of books in the library: "<< totalBooks << endl;}// Method to display information about the bookvoiddisplayBookInfo(){
          cout <<"Book Title: "<< title <<", Author: "<< author << endl;}};// Initialize the static data member outside the classint Book::totalBooks =0;intmain(){// Creating book objects (books being added to the library)
       Book book1("The Catcher in the Rye","J.D. Salinger");
       Book book2("To Kill a Mockingbird","Harper Lee");
       Book book3("1984","George Orwell");// Displaying the total number of books using the static methodBook::displayTotalBooks();// Displaying the details of each book
       book1.displayBookInfo();
       book2.displayBookInfo();
       book3.displayBookInfo();// Adding more books to the library
       Book book4("Pride and Prejudice","Jane Austen");
       Book book5("The Great Gatsby","F. Scott Fitzgerald");// Displaying the updated total number of booksBook::displayTotalBooks();return0;}

    Output

    Total number of books in the library: 3
    Book Title: The Catcher in the Rye, Author: J.D. Salinger
    Book Title: To Kill a Mockingbird, Author: Harper Lee
    Book Title: 1984, Author: George Orwell
    Total number of books in the library: 5
    

    Use Case of Static Data Members

    Static data members in C++ are the names given to those variables that can be accessed by all instances of a class. That is, they are not tied to any object. Let’s see some common use cases for it.

    1. Tracking object creation

    A very common usage of static data members is to track the number of instances or objects for a class.

    2. Maintaining global configurations or settings

    These are used to create global settings or configuration components that need to be accessed by all instances of a class in any context.

    3. Cache or Shared Resource Management

    Static data members are also useful for managing shared resources or caching in a system, where it’s possible for multiple objects to access the same resource.

    4. Implementing design patterns like Singleton

    The implementation of design patterns, such as Singleton, is also advantageous, as this particular pattern often uses static data members to ensure that there exists only one instance of a class throughout the entire program. The static member holds the exclusive instance of the class.

    5. Tracking global counters or actions across objects

    It also helps in tracking a global count of a particular object or action, like counting the number of logins, transactions, or events.