Min menu

Pages

VB

Overriding in C Plus | C++

Overriding concept in C++

Redefining concept inC++

In the previous lesson, you saw how when a class inherits from another class, it inherits the variables and functions in it.

Redefining or redefining(Overriding)It means defining the same function that the son class inherited from the father class again, and this new function is similar to the inherited function in terms of form only, that is, it has the same name, type and number of parameters, but its content is different in order to be more proportional to the son class.

The real goal of redefining or redefining is to give the son the opportunity to define the functions according to his needs.
In advanced lessons we will inherit from ready-made classes inC++, and we doOverridefor the functions in it to fit the applications we are going to build.


Conditions for redefining inherited functions in C++

  • must betheModifierThe user of the new function is the same as the user of the old function, and it must be of type publicorprotected.

  • The number and type of parameters of the new function must match the number and type of parameters of the old function.

  • The return type of the new function must be the same as the return type of the old function.

  • Knowledge functionKprivateWe can't do herOverride,Because the word privateprevents direct access to the function from the son class.

  • Knowledge functionKfinalWe can't do herOverride,Because a word finalprevents the function from changing after its definition.

  • Knowledge functionKstaticWe can't do herOverrideBut it can be defined again anywhere, because a word staticmakes the function common to all classes.

  • can not doOverridefor the constructor.

An example showing the usefulness of redefining functions inC++

In the following example, we have defined a class whose name Countryis the main class for any country.
In this class, we have defined a function called the language()idea of ​​printing the language of the country and we made it print the English language by default as the language of any country.

Then we defined three classes representing three different countries (Australia, Lebanon, Spain) so we made them inherit from the class Countrythat is the basis of any country.
So the three classes will inherit the functionlanguage().

Here the idea we want to convey is that any class that inherits Countrymay have to redefine the function language()in order for it to fit.
For example, Lebanon's language is Arabic, and Spain's language is Spanish.

After creating these classes, we create objects from them and call the function language()of each one of them to print the language people speak in it.

A practical example showing the usefulness of redefining functions in C++

main.cpp
#include <iostream>

using namespace std;

// which is the basic class for any country in the world, then it must be inherited by every class representing Country. Here we have defined the class
class Country {

	// Here we have defined a function that prints the country's language and made it print English as the default language for any country
    public:
        void language()
        {
            cout << "English \n";
        }

};


// Country and inherits from the Australia class. Here we have defined a class representing the country of Australia and its name
class Australia : public Country {
	
	// Again, because English is originally Australia's language() here there is no need to define the function

};


// Country and inherits from the class Lebanon. Here we have defined a class that represents the state of Lebanon and its name
class Lebanon : public Country {

	// Again, because English is not the language of Lebanon, language() here must define the function
    public:
        void language()
        {
            cout << "Arabic \n";
        }

};


// Country and inherits from the class Spain. Here we have defined a class that represents the country of Spain and its name
class Spain : public Country {

	// again because English is not the language of Spain language() here the function must be defined
    public:
        void language()
        {
            cout << "Spanish \n";
        }

};


// main() Here we have defined the function
int main()
{
    // Here we have created objects from the three countries
    Australia au;
    Lebanon lb;
    Spain sp;

    // To display the language of each country language() here we called the function
    au.language();
    lb.language();
    sp.language();

    return 0;
}
		

We will get the following result when running.

English
Arabic
Spanish
		


Now you understand what you might need to doOverride.
We will now explain how the translator works when we didOverridefor the functionlanguage().

If you go back to classLebanon,You'll find we didOverridefor the functionlanguage().
So here the class Lebanonactually has two functions namedlanguage(),The first is what he inherited from the class Country, and the second is what we define in it.


Since the class Lebanonhas two functions with the same name, type and number of parameters, how does the compiler know which function to choose?

When we define the function language()again in the class Lebanon(ie the son class) the compiler hides the original function that it inherited from the class Country(ie the parent class) and shows only the new function.


note

inside the classLebanon,You can still use the function language()in the class Countrythat the compiler hid when we defined it again, and this is what we will learn about in the following example.

Important concepts about redefining functions inC++


first concept

We noticed a while ago that when redefining the function that the son class inherited from the father class that the translator hides the function inherited by the son class and shows the one that was defined in it, but we said that the function in the father class can still be accessed by the son class even and If it had been hidden and that's what we will learn from this example.
Here we put an example of how to call the function in the parent class.

In the following example, we have defined a class whose name Basecontains a function whose name isprintMsg.
Then we defined a class whose name Derivedinherits from the class Baseand we redefined the function printMsgand another function whose name isprintBoth.

In the function printBoth()we call the function printMsg()inherited from the class Derivedand the function printMsg()that was redefined in it.

Finally, we create an object from the class Derivedand then call all the functions it has.

Example

main.cpp
      #include <iostream>

      using namespace std;

      // print contains one function named Base. Here we have defined a class named Base
      class Base
      {
      public:
      void print() {
      cout << "Base::print() \n";
      }
      };

      // also printBoth and another function named print and in it we have defined a function named Base that inherits from the Derived class. Here we have defined the class
      class Derived : public Base
      {
      public:
      void print()
      {
      cout << "Derived::print() \n";
      }

      void printBoth()
      { // printBoth() when the function is called
      Base::print(); // Base in the print() class will call the function
      print(); // in the same class as print() and then call the function
      }
      };

      // main() Here we have defined the function
      int main()
      {
      // d its name is Derived here we have created an object from the class
      Derived d;

      // Derived which is defined in class d of the print() object here we call the function
      d.print();

      // Base which is defined in class d of the print() object here we call the function
      d.Base::print();

      // which will call both of the previous functions Derived that were defined in class d from the print() object here we called the function
      d.printBoth();

      return 0;
      }
    

We will get the following result when running.

Derived::print()     --> Result of function call at line 37
Base::print()        --> Result of function call at line 40
Base::print()        --> Result of function call at line 43
Derived::print( )     --> the result of the function call in line 43


second concept

If you want to write the code in a way that is easy to deal with and review later, it is better to add the word virtualto any function you want the class that inherits to redefine it to fit with it, and in the class that inherits it is also better to add the word to the overridefunction that you redefine again in The son's class.

If you want to write the code in a way that is easy to deal with and review later, it is better to add the word virtualto any function you want the class that inherits to redefine it to fit with it, and in the class that inherits it is also better to add the word to the overridefunction that you redefine again in The son's class.

Note: These two words were added starting from the releaseC++11and subsequent versions.


In the following example, we have defined a class whose name Basecontains a function whose name funcand typevirtual void.
Then we defined a class whose name Derivedinherits from the class Baseand we redefined the function funcwith the addition of the word overridewhen it was defined.

Finally, we create an object from the class Derivedand then call the function func()in it.

Example

main.cpp
      #include <iostream>

      using namespace std;

      // func contains one function named Base. Here we have defined a class named
      class Base
      {
      public:
      virtual void func()
      {
      cout << "Base class default behavior \n";
      }
      };

      // also func and in it we have defined a function named Base that inherits from the Derived class. Here we have defined the class
      class Derived : public Base
      {
      public:
      void func() override
      {
      cout << "Derived class overridden behavior \n";
      }
      };

      // main() Here we have defined the function
      int main()
      {
      // d its name is Derived here we have created an object from the class
      Derived d;

      // Derived which is defined in class d of the func() object here we call the function
      d.func();

      return 0;
      }
    

We will get the following result when running.

      Derived class overridden behaviour
    

Technical information

In the previous example, if you remove the two words virtualand overrideit will not cause any problem or difference because, as we have already said, we put them only for the purpose of writing the code in a common way.

For the compiler, when placing the word virtualyou are given the option to put the word overridewhen redefining the function. But it does not allow you to put the word overrideif the function is not originally a typevirtual.


Returning to the lesson, you will learn more about the usefulness of the word virtualthat can be used to achieve the principle of abstraction(Abstraction).



The third concept

If you want to define the shape of the function(Prototype)Only in the class and forcing any class that inherits it to define it, you can use the word virtualto achieve this.
The style of writing the code used in this example is called abstraction(Abstraction).

abstraction concept inC++

abstraction(Abstraction)It is a very important method used to make it easier for programmers to write commands, as it makes you able to do what you want without having to know all the details in which it was implemented.

As a simple example, if you intend to build a program that allows its users to send suggestions about the application through e-mail, in this case you will not have to worry at all about the way orders are handledC++With the protocols that work when emails are sent through this app because you are not responsible for them. Actually, this is the job of the company that gives you a ready-made code that can be used to send an email and you will only have to specify the basic information such as the sender’s email, the recipient’s email, the message text etc..

So in general, abstraction makes you deal with things shallow rather than diving into the details of complex code.
This method will also pass you in later lessons when you learn a principle called polymorphism(Polymorphism).

Application of the principle of abstraction inC++

If you want to define the shape of the function(Prototype)Only in the class and forcing any class that inherits it to define it, you can follow the abstraction method to achieve this.

All you have to do to tell the compiler that you want to force the son class to define the function that it inherits from the father class itself is to define the function in the father class basically as an abstract function and here you will have to make its type virtualand make it equal 0only.


Abstraction technology terminology in C++

  • An abstract function is any function that implements the abstraction methodAbstract FunctionorPure Virtual Function.

  • An abstract class is any class that contains one or more abstract functionsAbstract Class.



Terms of abstraction in C++

When applying the abstraction method, you should pay attention to the following points:

  • A class containing abstract functions cannot create objects from it because if a function is called that is not defined from it, this will cause a problem.

  • A class that inherits abstract functions and does not rewrite their content also cannot create objects from it for the same reason.

  • Static functions whose type staticcannot be defined as abstract functions because they are originally used from the base class.

  • The abstraction method requires the use of the two words virtual, overridewhich were added starting from the versionC++11So make sure you are using this version or newer versions to be able to apply it.



In the following example, we have defined a class whose name Basecontains an abstract function whose name isfunc.
Then we defined a class whose name Derivedinherits from the class Baseand in it we redefined the functionfunc.

Finally, we create an object from the class Derivedand then call the function func()in it.

first example

main.cpp
        #include <iostream>

        using namespace std;

        // func contains an abstract function named Base. Here we have defined a class named
        class Base
        {
        public:
        virtual void func() = 0;
        };

        // func and in it we have defined the abstract function Base, which inherits from the Derived class. Here we have defined the content of the class
        class Derived : public Base
        {
        public:
        void func() override
        {
        cout << "Derived class overridden behavior \n";
        }
        };

        // main() Here we have defined the function
        int main()
        {
        // d its name is Derived here we have created an object from the class
        Derived d;

        // Derived which is defined in class d of the func() object here we call the function
        d.func();

        return 0;
        }
      

We will get the following result when running.

        Derived class overridden behaviour
      


We will repeat the same example as before, but we will try to create an object from the parent class that contains the abstract function to alert you of the error that may appear to you if you do so.
Note: We have modified the lines that we have changed in yellow.

second example

main.cpp
        #include <iostream>

        using namespace std;

        // func contains an abstract function named Base. Here we have defined a class named
        class Base
        {
        public:
        virtual void func() = 0;
        };

        // func and in it we have defined the abstract function Base, which inherits from the Derived class. Here we have defined the content of the class
        class Derived : public Base
        {
        public:
        void func() override
        {
        cout << "Derived class overridden behavior \n";
        }
        };

        // main() Here we have defined the function
        int main()
        {
        // b named Base. Here we have created an object from the class
        Base b;

        // Base which is defined in class b of the func() object here we call the function
        b.func();

        return 0;
        }
      

We will get the following result when running.

Error: cannot declare variable 'b' to be of abstract type 'Base'
    because the following virtual functions are pure within 'Base':
        'virtual void Base::func()'

Note that the error actually occurred due to line 26 as the compiler said that an object cannot be created from the class Basebecause it contains an abstract function(Pure Virtual Function)Then he wrote us the name of the abstract function as well.



Fourth concept

If you want to prevent the child class from redefining the function it inherited from the class, you can make the type of the function virtual finalso that you can make the entire class type finalnot redefine any function in it in order to use the functions in it as is.

word finalinC++

If you want to prevent the child class from redefining the function it inherited from the class, you can make the type of the function virtual finalso that you can make the entire class type finalnot redefine any function in it in order to use the functions in it as is.

Note: This word has been added since the releaseC++11and subsequent versions.


technical terms

  • A function that cannot be redefined is usually called a constant function.

  • A class in which nothing in it can be redefined is called a fixed class.



The fixed class does not allow you to inherit from it, because inheritance is basically the idea that you inherit something with the aim of developing it or increasing it.
In other words, you can create objects only from it and use what is in it.

The word finalcan be used as a name for a variable, function, array, object, etc., because it is not considered a reserved word.(Keywords)in the language.

Comprehensive examples of the word finalinC++


In the following example, we have defined a class whose name Basecontains a constant function namedfunc().
Then we defined a class whose name Derivedinherits from the class Base, and we tried to redefine the function func()to alert you of the error that may appear if you try to redefine a static function in the class that inherits it.

first example

main.cpp
      #include <iostream>

      using namespace std;

      // func contains a static function named Base. Here we have defined a class named
      class Base
      {
      public:
      virtual void func() final
      {
      cout << "Base class default behavior \n";
      }
      };

      // func In it we have redefined the static function Base inherits from the Derived class Here we have defined the content of the class
      class Derived : public Base
      {
      public:
      void func() override // This is the line that will cause the problem when running
      {
      cout << "Derived class overridden behavior \n";
      }
      };

      // main() Here we have defined the function
      int main()
      {
      return 0;
      }
    

The following error will appear when running.

error: virtual function 'virtual void Derived::func()' overriding final function
    note: overridden function is 'virtual void Base::func()'
        In member function 'virtual void Derived::func()'

In the previous example, the error actually occurred because of line 19 , as the compiler said that the function cannot be redefined func()in the class Derivedthat inherited it because in the parent class it is Basedefined as a constant.



In the following example, we have defined a fixed class whose name Basecontains a function whose name isfunc().
Then we defined a class whose name Derivedinherits from the class Baseonly to warn you of the error that may appear if you try to inherit from a fixed class.

second example

main.cpp
      #include <iostream>

      using namespace std;

      // func contains a function named Base. Here we have defined a constant class named
      class Base final
      {
      public:
      void func()
      {
      cout << "Base class default behavior \n";
      }
      };

      // Of course, this command will cause a problem when running Base inherits from the Derived class. Here we have defined the content of the class
      class Derived : public Base
      {

      };

      // main() Here we have defined the function
      int main()
      {
      return 0;
      }
    

The following error will appear when running.

error: cannot derive from 'final' base 'Base' in derived type 'Derived'

In the previous example, the error actually occurred due to line 16 , as the compiler said that it is not possible to inherit from the class Basebecause it is a fixed class.



In the following example, we have defined a fixed class whose name Basecontains a function whose name isfunc().
Then we create an object from it and call the function in it.

third example

main.cpp
      #include <iostream>

      using namespace std;

      // func contains a function named Base. Here we have defined a constant class named
      class Base final
      {
      public:
      void func()
      {
      cout << "Base class default behavior \n";
      }
      };

      // main() Here we have defined the function
      int main()
      {
      // b named Base. Here we have created an object from the class
      Base b;

      // b from the func() object here we called the function
      b.func();

      return 0;
      }
    

We will get the following result when running.

      Base class default behaviour