Category: C++ Object-oriented

https://zain.sweetdishy.com/wp-content/uploads/2026/02/Object-oriented-.png

  • Final Specifier in C++

    The final specifier was introduced in C++11 with two main purposes −

    • The first purpose is to prevent inheritance. When a class is marked with final, other classes can not inherit from it.
    • The second purpose it to avoid function overriding. When you mark a virtual function with final, then it can not be overridden in the derived classes.

    Read this chapter to learn how to use the final specifier in C++.

    Using the final Specifier with Class

    You can mark a class as final to prevent inheritance. After marking a class as final, you can no longer use this class for inheritance. Other classes will not be able to inherit them.

    The syntax for using final specifier with a class is given below −

    classMyClassfinal{// class members};

    Example

    Here is an example demonstrating the difference between a class when used with final and when used without final −

    Class with final Class without final

    In this example, we are using the final specifier with Base class and the Derived class is inheriting the base class. It will give an error in output as shown below −

    #include <iostream>usingnamespace std;classBasefinal// final class{public:voiddisplay(){
          cout <<"Base class"<< endl;}};// Inheriting from final classclassDerived:public Base{public:voidshow(){
          cout <<"Derived class"<< endl;}};intmain(){
       Base b;
       b.display();return0;}

    The output of the above code is given below −

    main.cpp:14:7: error: cannot derive from 'final' base 'Base' in derived 
    type 'Derived'
       14 | class Derived : public Base
          |       ^~~~~~~
    

    Using the final Specifier with Function

    You can mark a function with final to avoid overriding the function. After marking a function as final, you can no longer override that function. The function can only be made final if the function is a virtual function.

    The syntax to use final specifier with a function is given below −

    classBase{public:virtualvoiddisplay()final{// implementation}};

    Example

    The example below demonstrates the difference between a function when used with final and when used without final −

    Function with final Function without final

    In this example, we have used final specifier on the virtual function breathe() in Mammal class. In the Dog class, we are trying to override the breathe() function which will give an error in the output.

    #include <iostream>usingnamespace std;classAnimal{public:virtualvoidmakeSound(){
          cout <<"Animal sound"<< endl;}virtualvoidbreathe(){
          cout <<"Animal breathing"<< endl;}};classMammal:public Animal{public:voidmakeSound()override{
          cout <<"Mammal sound"<< endl;}// final functionvoidbreathe()finaloverride{
          cout <<"Mammal breathing"<< endl;}};classDog:public Mammal{public:voidmakeSound()override{
          cout <<"Bark"<< endl;}// This would cause an errorvoidbreathe()override{ 
          cout <<"Dog breathing"<< endl;}};intmain(){
       Dog dog;
       dog.makeSound(); 
       dog.breathe();return0;}

    The output of the above code is as follows −

    main.cpp:42:10: error: virtual function 'virtual void Dog::breathe()' overriding 
    final function
       42 |     void breathe() override
          |          ^~~~~~~
    main.cpp:27:10: note: overridden function is 'virtual void Mammal::breathe()'
       27 |     void breathe() final override
          |          ^~~~~~~
    

    Conclusion

    The final specifier in C++ helps in preventing the inheritance of classes and the overriding of the virtual function. In this chapter, we explained in detail how the final specifier works with class and virtual function.

  • Override Specifier in C++

    Function overriding is an example of run-time polymorphism in C++, where we redefine the function of a base class in the derived class. The function namereturn type, and parameters should be same in base as well as derived class functions.

    What is override Specifier?

    The override specifier in C++ is used to override a function and it makes sure that overriding is done correctly. It is useful in finding the mistakes while overriding a function.

    If the override specifier is not used while overriding, then the function will run normally without giving any error as it will consider it a different function. So, we use an override specifier to overcome this problem, as the compiler will generate an error if the function is not overridden correctly.

    Function Overriding using override Specifier

    Here is an example of function overriding of speak() function using override specifier:

    #include<iostream> usingnamespace std;classAnimal{public:virtualvoidspeak(){
          cout <<"Animal speaking"<< endl;}};classDog:public Animal{public:voidspeak()override// overriding speak function{ 
          cout <<"Dog barking"<< endl;}};intmain(){
       Animal *animal =newAnimal();
       Animal *dog =newDog();
    
       animal->speak(); 
       dog->speak();delete animal;delete dog;
       cout << endl;}

    The output of the above code is as follows −

    Animal speaking
    Dog barking
    

    Rules of Using override Specifier

    You need to follow some rules while using the override specifier. These rules are mentioned below −

    • The function in the base class needs to be a virtual function.
    • The function name and signatures (number of parameters and their types, return type, and const qualifiers) should be same, otherwise it will give an error.

    Benefits of Using override Specifier

    The benefit of using an override specifier is that it ensures correct implementation of the function overriding. It can solve following problems if override specifier is used −

    Using Wrong Function Name

    When you make a mistake while writing a function name, the program will run normally if override specifier is not used. With override specifier, it will give an error.

    Without override With override

    In this example, there is a typo in the function name. Instead of showing any error, it will run the speak() function of Animal class −

    #include <iostream>usingnamespace std;classAnimal1{public:virtualvoidspeak(){
          cout <<"Animal Speaking"<< endl;}};classDog1:public Animal1{public:voidspeek()// Wrong function name{ 
          cout <<"Dog Barking"<< endl;}};intmain(){
       Animal1 *dog =newDog1();
       dog->speak();delete dog;
       cout << endl;}

    The output of the above code is as follows −

    Animal Speaking
    

    Wrong Parameter Type

    If you define a wrong parameter type while overriding, the program will run normally if override specifier is not used. With override specifier, it will give an error.

    Without override With override

    In this example, we want to call the calculate() function of class2, but due to a different parameter type, calculate() function of Class1 is called without displaying any error −

    #include <iostream>usingnamespace std;classClass1{public:virtualvoidcalculate(int x){
          cout <<"Result: "<< x *2<< endl;}};classClass2:public Class1{public:voidcalculate(double x)// Different parameter type{ 
          cout <<"Result: "<< x *3<< endl;}};intmain(){
       Class1 *calc =newClass2();
       calc->calculate(5);delete calc;
       cout << endl;}

    The output of the above code is as follows −

    Result: 10
    

    Conclusion

    The override specifier in C++ is used to avoid function overriding mistakes. It is always used with virtual functions and ensures that the function overriding is implemented correctly without any errors.

  • C++ – Pure Virtual Functions and Abstract Classes

    Pure Virtual Functions and Abstract Classes

    A pure virtual function is a virtual function in C++ for which we need not write any function definition and only have to declare it, where it is declared by assigning 0 in the declaration. To declare a virtual function, use the “virtual” keyword. 

    Whereas, an abstract class is a class in C++ which have at least one pure virtual function.

    Syntax

    virtual return_type func_name(parameters)=0;

    Where

    • return_type is the return type of the function (e.g., int, void, etc.)
    • func_name is the name of the function.
    • parameters is the list of parameters the function.
    • = 0 syntax indicates that the function is pure virtual, which has no definition in the base class.

    Example of Pure Virtual Function

    classShape{public:// Pure virtual functionvirtualvoiddraw()=0;};

    Example of Abstract Class

    An abstract class is a class that contains at least one pure virtual function.

    classShape{public:virtualvoiddraw()=0;// Pure virtual function makes Shape an abstract classvirtual~Shape(){}// Virtual destructor (good practice)};

    Example of Pure Virtual Functions and Abstract Classes

    Here is the full example showcasing the working of it.

    #include<iostream>usingnamespace std;// Abstract classclassShape{public:virtualvoiddraw()=0;// Pure virtual functionvirtual~Shape(){}// Virtual destructor};// Derived class: CircleclassCircle:public Shape{public:voiddraw()override{
        cout <<"Drawing Circle"<< endl;}};// Derived class: RectangleclassRectangle:public Shape{public:voiddraw()override{
        cout <<"Drawing Rectangle"<< endl;}};// Derived class: TriangleclassTriangle:public Shape{public:voiddraw()override{
        cout <<"Drawing Triangle"<< endl;}};intmain(){
      Shape * shapes[]={newCircle(),newRectangle(),newTriangle()};// Draw all shapesfor(Shape * shape: shapes){
        shape ->draw();}// Cleanupfor(Shape * shape: shapes){delete shape;}return0;}

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

    Drawing Circle
    Drawing Rectangle
    Drawing Triangle

    Key Features of Abstract Classes

    • Abstract classes can have normal functions and variables too, along with a pure virtual function.
    • Abstract class cannot be instantiated, but pointers and references of Abstract class type can be created.
    • Abstract classes are mainly used for Upcasting so that their derived classes can use its interface.
    • If an Abstract Class has a derived class, it must implement all pure virtual functions, or else they will become Abstract too.
    • We cant create an object of abstract class as we reserve a slot for a pure virtual function in Vtable, but we dont put any address, so Vtable will remain incomplete.
  • Virtual Function in C++

    A virtual function in C++ is a member function in a base class, which is further overridden in derived classes. This helps in enabling runtime polymorphism, which means the function to be executed is determined at runtime, not compile-time as the function that gets called depends on the actual object type, not the pointer or reference type.

    Virtual Function Declaration

    A virtual function is declared in the base class using the virtual keyword.

    Syntax

    Below is the syntax of virtual function declaration:

    classBaseClassName{public:virtualvoidfunc_name(){// implementation}};

    Where,

    • BaseClassName is the name of a base class given by a user.
    • func_name is the name of a function given.

    How Virtual Functions Work

    In C++, Virtual Functions allow runtime polymorphism, which means the function, that gets called depends on the actual object type, not the pointer or reference type, and this is done by using a mechanism called the vtable (virtual table) and vptr (virtual table pointer).

    Virtual Table (VTable) and Virtual Pointer (VPTR)

    Virtual Table is a table of function pointers, which is created for each class that has virtual functions, it stores addresses of virtual functions of the class.
    Whereas each object of that class with virtual functions contains a hidden vptr, where this vptr points to the vtable of its class.

    Step-by-Step Working

    1. When we declare a function as virtual in the base class, it enables dynamic binding instead of static binding.
    2. For a class with virtual functions, the compiler creates a vtable, which stores pointers to those functions.
    3. Here each object of a class with virtual functions has a vptr, which points to the class’s vtable.
    4. Then a base class pointer uses vptr to fetch the correct function from the vtable at runtime, ensuring the derived class’s overridden function is called.

    Example

    #include<iostream>usingnamespace std;classshape{public:virtualvoiddraw(){// Virtual function
        cout <<"Creating a shape!"<< endl;}};classcircle:public shape{public:voiddraw(){// Overriding virtual function
        cout <<"Creating a Circle!"<< endl;}};classsquare:public shape{public:voiddraw(){// Overriding virtual function
        cout <<"Creating a Square!"<< endl;}};intmain(){
      shape * shapePtr;// Base class pointer
      circle c;
      square s;
    
      shapePtr =& c;// Pointing to circle object
      shapePtr ->draw();// Calls circle's draw() method
    
      shapePtr =& s;// Pointing to square object
      shapePtr ->draw();// Calls square's draw() methodreturn0;}

    Output

    Creating a Circle!
    Creating a Square!

    Explanation

    1. Firstly, a base class named shape is created with virtual function draw(), therefor it will set up the mechanism of VTable for this class.
    2. Now the circle class inherits from shape and overrides draw(), so when a circle object is used, then its draw() function is called.
    3. Similar to the circle, the square class will also override the draw() function.
    4. Now, in int main(), shape* shapePtr; is a pointer of type shape, which will point to objects of circle or square.
    5. shapePtr = &c; this base class pointer points to the circle object c and shapePtr->draw(); calls circle’s draw() function.
    6. Similarly, shapePtr = &s; this base class pointer points to the square object s and shapePtr->draw(); calls square’s draw() function.

    Rules for Virtual Functions

    1. Virtual function must be declared in the base class using the “virtual” keyword. If virtual is omitted, overriding will not work dynamically.
    2. Virtual functions must be accessed through a base class pointer or reference. If it is accessed directly using an object then compile-time binding will occur.
    3. With a virtual function, a base class must also have a virtual destructor to prevent memory leaks. In case the destructor is not virtual then only the base class destructor will be called, causing a memory leak.
    4. A Class with a pure virtual function becomes an abstract class and cannot be instantiated and If a derived class does not override a pure virtual function, It also becomes abstract.
      classBase{public:virtualvoidshow()=0;// Pure virtual function};
    5. Virtual can be both public and private where public can be accessed using an object or pointer but private cannot be accessed directly but it can still be inherited and overridden in the derived class.
    6. Constructors, Static, and Friend Functions cannot be virtual.
  • Interfaces in C++ (Abstract Classes)

    An interface describes the behavior or capabilities of a C++ class without committing to a particular implementation of that class.

    The C++ interfaces are implemented using abstract classes and these abstract classes should not be confused with data abstraction which is a concept of keeping implementation details separate from associated data.

    A class is made abstract by declaring at least one of its functions as pure virtual function. A pure virtual function is specified by placing “= 0” in its declaration as follows −

    classBox{public:// pure virtual functionvirtualdoublegetVolume()=0;private:double length;// Length of a boxdouble breadth;// Breadth of a boxdouble height;// Height of a box};

    The purpose of an abstract class (often referred to as an ABC) is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface. Attempting to instantiate an object of an abstract class causes a compilation error.

    Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the virtual functions, which means that it supports the interface declared by the ABC. Failure to override a pure virtual function in a derived class, then attempting to instantiate objects of that class, is a compilation error.

    Classes that can be used to instantiate objects are called concrete classes.

    Abstract Class Example

    Consider the following example where parent class provides an interface to the base class to implement a function called getArea() −

    #include <iostream>usingnamespace std;// Base classclassShape{public:// pure virtual function providing interface framework.virtualintgetArea()=0;voidsetWidth(int w){
             width = w;}voidsetHeight(int h){
             height = h;}protected:int width;int height;};// Derived classesclassRectangle:public Shape{public:intgetArea(){return(width * height);}};classTriangle:public Shape{public:intgetArea(){return(width * height)/2;}};intmain(void){
       Rectangle Rect;
       Triangle  Tri;
     
       Rect.setWidth(5);
       Rect.setHeight(7);// Print the area of the object.
       cout <<"Total Rectangle area: "<< Rect.getArea()<< endl;
    
       Tri.setWidth(5);
       Tri.setHeight(7);// Print the area of the object.
       cout <<"Total Triangle area: "<< Tri.getArea()<< endl;return0;}

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

    Total Rectangle area: 35
    Total Triangle area: 17
    

    You can see how an abstract class defined an interface in terms of getArea() and two other classes implemented same function but with different algorithm to calculate the area specific to the shape.

    Designing Strategy

    An object-oriented system might use an abstract base class to provide a common and standardized interface appropriate for all the external applications. Then, through inheritance from that abstract base class, derived classes are formed that operate similarly.

    The capabilities (i.e., the public functions) offered by the external applications are provided as pure virtual functions in the abstract base class. The implementations of these pure virtual functions are provided in the derived classes that correspond to the specific types of the application.

    This architecture also allows new applications to be added to a system easily, even after the system has been defined.

  • Data Encapsulation in C++

    All C++ programs are composed of the following two fundamental elements −

    • Program statements (code) − This is the part of a program that performs actions and they are called functions.
    • Program data − The data is the information of the program which gets affected by the program functions.

    Encapsulation is an Object Oriented Programming concept that binds together the data and functions that manipulate the data, and that keeps both safe from outside interference and misuse. Data encapsulation led to the important OOP concept of data hiding.

    Data encapsulation is a mechanism of bundling the data, and the functions that use them and data abstraction is a mechanism of exposing only the interfaces and hiding the implementation details from the user.

    C++ supports the properties of encapsulation and data hiding through the creation of user-defined types, called classes. We already have studied that a class can contain private, protected and public members. By default, all items defined in a class are private. For example −

    classBox{public:doublegetVolume(void){return length * breadth * height;}private:double length;// Length of a boxdouble breadth;// Breadth of a boxdouble height;// Height of a box};

    The variables length, breadth, and height are private. This means that they can be accessed only by other members of the Box class, and not by any other part of your program. This is one way encapsulation is achieved.

    To make parts of a class public (i.e., accessible to other parts of your program), you must declare them after the public keyword. All variables or functions defined after the public specifier are accessible by all other functions in your program.

    Making one class a friend of another exposes the implementation details and reduces encapsulation. The ideal is to keep as many of the details of each class hidden from all other classes as possible.

    Data Encapsulation Example

    Any C++ program where you implement a class with public and private members is an example of data encapsulation and data abstraction. Consider the following example −

    #include <iostream>usingnamespace std;classAdder{public:// constructorAdder(int i =0){
             total = i;}// interface to outside worldvoidaddNum(int number){
             total += number;}// interface to outside worldintgetTotal(){return total;};private:// hidden data from outside worldint total;};intmain(){
       Adder a;
       
       a.addNum(10);
       a.addNum(20);
       a.addNum(30);
    
       cout <<"Total "<< a.getTotal()<<endl;return0;}

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

    Total 60
    

    Above class adds numbers together, and returns the sum. The public members addNum and getTotal are the interfaces to the outside world and a user needs to know them to use the class. The private member total is something that is hidden from the outside world, but is needed for the class to operate properly.

    Designing Strategy

    Most of us have learnt to make class members private by default unless we really need to expose them. That’s just good encapsulation.

    This is applied most frequently to data members, but it applies equally to all members, including virtual functions.

  • Data Abstraction in C++

    Data abstraction refers to providing only essential information to the outside world and hiding their background details, i.e., to represent the needed information in program without presenting the details.

    Data abstraction is a programming (and design) technique that relies on the separation of interface and implementation.

    Let’s take one real life example of a TV, which you can turn on and off, change the channel, adjust the volume, and add external components such as speakers, VCRs, and DVD players, BUT you do not know its internal details, that is, you do not know how it receives signals over the air or through a cable, how it translates them, and finally displays them on the screen.

    Thus, we can say a television clearly separates its internal implementation from its external interface and you can play with its interfaces like the power button, channel changer, and volume control without having any knowledge of its internals.

    In C++, classes provides great level of data abstraction. They provide sufficient public methods to the outside world to play with the functionality of the object and to manipulate object data, i.e., state without actually knowing how class has been implemented internally.

    For example, your program can make a call to the sort() function without knowing what algorithm the function actually uses to sort the given values. In fact, the underlying implementation of the sorting functionality could change between releases of the library, and as long as the interface stays the same, your function call will still work.

    In C++, we use classes to define our own abstract data types (ADT). You can use the cout object of class ostream to stream data to standard output like this −

    #include <iostream>usingnamespace std;intmain(){
       cout <<"Hello C++"<<endl;return0;}

    Here, you don’t need to understand how cout displays the text on the user’s screen. You need to only know the public interface and the underlying implementation of cout is free to change.

    Access Labels Enforce Abstraction

    In C++, we use access labels to define the abstract interface to the class. A class may contain zero or more access labels −

    • Members defined with a public label are accessible to all parts of the program. The data-abstraction view of a type is defined by its public members.
    • Members defined with a private label are not accessible to code that uses the class. The private sections hide the implementation from code that uses the type.

    There are no restrictions on how often an access label may appear. Each access label specifies the access level of the succeeding member definitions. The specified access level remains in effect until the next access label is encountered or the closing right brace of the class body is seen.

    Benefits of Data Abstraction

    Data abstraction provides two important advantages −

    • Class internals are protected from inadvertent user-level errors, which might corrupt the state of the object.
    • The class implementation may evolve over time in response to changing requirements or bug reports without requiring change in user-level code.

    By defining data members only in the private section of the class, the class author is free to make changes in the data. If the implementation changes, only the class code needs to be examined to see what affect the change may have. If data is public, then any function that directly access the data members of the old representation might be broken.

    Data Abstraction Example

    Any C++ program where you implement a class with public and private members is an example of data abstraction. Consider the following example −

    #include <iostream>usingnamespace std;classAdder{public:// constructorAdder(int i =0){
             total = i;}// interface to outside worldvoidaddNum(int number){
             total += number;}// interface to outside worldintgetTotal(){return total;};private:// hidden data from outside worldint total;};intmain(){
       Adder a;
       
       a.addNum(10);
       a.addNum(20);
       a.addNum(30);
    
       cout <<"Total "<< a.getTotal()<<endl;return0;}

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

    Total 60
    

    Above class adds numbers together, and returns the sum. The public members – addNum and getTotal are the interfaces to the outside world and a user needs to know them to use the class. The private member total is something that the user doesn’t need to know about, but is needed for the class to operate properly.

    Designing Strategy

    Abstraction separates code into interface and implementation. So while designing your component, you must keep interface independent of the implementation so that if you change underlying implementation then interface would remain intact.

    In this case whatever programs are using these interfaces, they would not be impacted and would just need a recompilation with the latest implementation.

  • Polymorphism in C++

    The word polymorphism means having many forms. Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.

    C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.

    Consider the following example where a base class has been derived by other two classes −

    #include <iostream> usingnamespace std;classShape{protected:int width, height;public:Shape(int a =0,int b =0){
             width = a;
             height = b;}intarea(){
             cout <<"Parent class area :"<< width * height << endl;return width * height;}};classRectangle:public Shape{public:Rectangle(int a =0,int b =0):Shape(a, b){}intarea(){ 
             cout <<"Rectangle class area :"<< width * height << endl;return(width * height);}};classTriangle:public Shape{public:Triangle(int a =0,int b =0):Shape(a, b){}intarea(){ 
             cout <<"Triangle class area :"<<(width * height)/2<< endl;return(width * height /2);}};// Main function for the programintmain(){
       Shape *shape;
       Rectangle rec(10,7);
       Triangle  tri(10,5);// store the address of Rectangle
       shape =&rec;// call rectangle area.
       shape->area();// store the address of Triangle
       shape =&tri;// call triangle area.
       shape->area();return0;}

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

    Parent class area :70
    Parent class area :50
    

    The reason for the incorrect output is that the call of the function area() is being set once by the compiler as the version defined in the base class. This is called static resolution of the function call, or static linkage – the function call is fixed before the program is executed. This is also sometimes called early binding because the area() function is set during the compilation of the program.

    But now, let’s make a slight modification in our program and precede the declaration of area() in the Shape class with the keyword virtual so that it looks like this −

    #include <iostream>usingnamespace std;classShape{protected:int width, height;public:Shape(int a =0,int b =0){
             width = a;
             height = b;}virtualintarea(){
             cout <<"Parent class area :"<< width * height << endl;return width * height;}};classRectangle:public Shape{public:Rectangle(int a =0,int b =0):Shape(a, b){}intarea(){
             cout <<"Rectangle class area :"<< width * height << endl;return(width * height);}};classTriangle:public Shape{public:Triangle(int a =0,int b =0):Shape(a, b){}intarea(){
             cout <<"Triangle class area :"<<(width * height)/2<< endl;return(width * height /2);}};// Main function for the programintmain(){
       Shape *shape;
       Rectangle rec(10,7);
       Triangle  tri(10,5);// store the address of Rectangle
       shape =&rec;// call rectangle area.
       shape->area();// store the address of Triangle
       shape =&tri;// call triangle area.
       shape->area();return0;}

    After this slight modification, when the previous example code is compiled and executed, it produces the following result −

    Rectangle class area :70
    Triangle class area :25
    

    This time, the compiler looks at the contents of the pointer instead of it’s type. Hence, since addresses of objects of tri and rec classes are stored in *shape the respective area() function is called.

    As you can see, each of the child classes has a separate implementation for the function area(). This is how polymorphism is generally used. You have different classes with a function of the same name, and even the same parameters, but with different implementations.

    Virtual Function

    virtual function is a function in a base class that is declared using the keyword virtual. Defining in a base class a virtual function, with another version in a derived class, signals to the compiler that we don’t want static linkage for this function.

    What we do want is the selection of the function to be called at any given point in the program to be based on the kind of object for which it is called. This sort of operation is referred to as dynamic linkage, or late binding.

    Pure Virtual Functions

    It is possible that you want to include a virtual function in a base class so that it may be redefined in a derived class to suit the objects of that class, but that there is no meaningful definition you could give for the function in the base class.

    We can change the virtual function area() in the base class to the following −

    classShape{protected:int width, height;public:Shape(int a =0,int b =0){
             width = a;
             height = b;}// pure virtual functionvirtualintarea()=0;};

    The = 0 tells the compiler that the function has no body and above virtual function will be called pure virtual function.

  • C++ Overloading (Operator and Function)

    C++ allows you to specify more than one definition for a function name or an operator in the same scope, which is called function overloading and operator overloading respectively.

    An overloaded declaration is a declaration that is declared with the same name as a previously declared declaration in the same scope, except that both declarations have different arguments and obviously different definition (implementation).

    When you call an overloaded function or operator, the compiler determines the most appropriate definition to use, by comparing the argument types you have used to call the function or operator with the parameter types specified in the definitions. The process of selecting the most appropriate overloaded function or operator is called overload resolution.

    Function Overloading in C++

    You can have multiple definitions for the same function name in the same scope. The definition of the function must differ from each other by the types and/or the number of arguments in the argument list. You cannot overload function declarations that differ only by return type.

    Read: C++ Function Overloading

    Following is the example where same function print() is being used to print different data types −

    #include <iostream>usingnamespace std;classprintData{public:voidprint(int i){
            cout <<"Printing int: "<< i << endl;}voidprint(double  f){
            cout <<"Printing float: "<< f << endl;}voidprint(char* c){
            cout <<"Printing character: "<< c << endl;}};intmain(void){
       printData pd;// Call print to print integer
       pd.print(5);// Call print to print float
       pd.print(500.263);// Call print to print character
       pd.print("Hello C++");return0;}

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

    Printing int: 5
    Printing float: 500.263
    Printing character: Hello C++
    

    Operators Overloading in C++

    You can redefine or overload most of the built-in operators available in C++. Thus, a programmer can use operators with user-defined types as well.

    Overloaded operators are functions with special names: the keyword “operator” followed by the symbol for the operator being defined. Like any other function, an overloaded operator has a return type and a parameter list.

    Box operator+(const Box&);

    declares the addition operator that can be used to add two Box objects and returns final Box object. Most overloaded operators may be defined as ordinary non-member functions or as class member functions. In case we define above function as non-member function of a class then we would have to pass two arguments for each operand as follows −

    Box operator+(const Box&,const Box&);

    Following is the example to show the concept of operator over loading using a member function. Here an object is passed as an argument whose properties will be accessed using this object, the object which will call this operator can be accessed using this operator as explained below −

    #include <iostream>usingnamespace std;classBox{public:doublegetVolume(void){return length * breadth * height;}voidsetLength(double len ){
             length = len;}voidsetBreadth(double bre ){
             breadth = bre;}voidsetHeight(double hei ){
             height = hei;}// Overload + operator to add two Box objects.
          Box operator+(const Box& b){
             Box box;
             box.length =this->length + b.length;
             box.breadth =this->breadth + b.breadth;
             box.height =this->height + b.height;return box;}private:double length;// Length of a boxdouble breadth;// Breadth of a boxdouble height;// Height of a box};// Main function for the programintmain(){
       Box Box1;// Declare Box1 of type Box
       Box Box2;// Declare Box2 of type Box
       Box Box3;// Declare Box3 of type Boxdouble volume =0.0;// Store the volume of a box here// box 1 specification
       Box1.setLength(6.0); 
       Box1.setBreadth(7.0); 
       Box1.setHeight(5.0);// box 2 specification
       Box2.setLength(12.0); 
       Box2.setBreadth(13.0); 
       Box2.setHeight(10.0);// volume of box 1
       volume = Box1.getVolume();
       cout <<"Volume of Box1 : "<< volume <<endl;// volume of box 2
       volume = Box2.getVolume();
       cout <<"Volume of Box2 : "<< volume <<endl;// Add two object as follows:
       Box3 = Box1 + Box2;// volume of box 3
       volume = Box3.getVolume();
       cout <<"Volume of Box3 : "<< volume <<endl;return0;}

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

    Volume of Box1 : 210
    Volume of Box2 : 1560
    Volume of Box3 : 5400
    

    Overloadable/Non-overloadableOperators

    Following is the list of operators which can be overloaded −

    +*/%^
    &|~!,=
    <><=>=++
    <<>>==!=&&||
    +=-=/=%=^=&=
    |=*=<<=>>=[]()
    ->->*newnew []deletedelete []

    Following is the list of operators, which can not be overloaded −

    ::.*.?:

    Operator Overloading Examples

    Here are various operator overloading examples to help you in understanding the concept.

    Sr.NoOperators & Example
    1Unary Operators Overloading
    2Binary Operators Overloading
    3Relational Operators Overloading
    4Input/Output Operators Overloading
    5++ and — Operators Overloading
    6Assignment Operators Overloading
    7Function call () Operator Overloading
    8Subscripting [] Operator Overloading
    9Class Member Access Operator -> Overloading