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
public
orprotected
.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 functionK
private
We can't do herOverride,Because the wordprivate
prevents direct access to the function from the son class.Knowledge functionK
final
We can't do herOverride,Because a wordfinal
prevents the function from changing after its definition.Knowledge functionK
static
We can't do herOverrideBut it can be defined again anywhere, because a wordstatic
makes 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 Country
is 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 Country
that 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 Country
may 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++
#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 Lebanon
actually 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 Lebanon
has 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 Country
that 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 Base
contains a function whose name isprintMsg
.
Then we defined a class whose name Derived
inherits from the class Base
and we redefined the function printMsg
and another function whose name isprintBoth
.
In the function printBoth()
we call the function printMsg()
inherited from the class Derived
and the function printMsg()
that was redefined in it.
Finally, we create an object from the class Derived
and then call all the functions it has.
Example
#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.
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 virtual
to 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 override
function 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 virtual
to 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 override
function 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 Base
contains a function whose name func
and typevirtual void
.
Then we defined a class whose name Derived
inherits from the class Base
and we redefined the function func
with the addition of the word override
when it was defined.
Finally, we create an object from the class Derived
and then call the function func()
in it.
Example
#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 virtual
and override
it 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 virtual
you are given the option to put the word override
when redefining the function. But it does not allow you to put the word override
if the function is not originally a typevirtual
.
Returning to the lesson, you will learn more about the usefulness of the word virtual
that 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 virtual
to 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 virtual
and make it equal 0
only.
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
static
cannot 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
,override
which 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 Base
contains an abstract function whose name isfunc
.
Then we defined a class whose name Derived
inherits from the class Base
and in it we redefined the functionfunc
.
Finally, we create an object from the class Derived
and then call the function func()
in it.
first example
#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
#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.
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 Base
because 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 final
so that you can make the entire class type final
not redefine any function in it in order to use the functions in it as is.
word final
inC++
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 final
so that you can make the entire class type final
not 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 final
can 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 final
inC++
In the following example, we have defined a class whose name Base
contains a constant function namedfunc()
.
Then we defined a class whose name Derived
inherits 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
#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.
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 Derived
that inherited it because in the parent class it is Base
defined as a constant.
In the following example, we have defined a fixed class whose name Base
contains a function whose name isfunc()
.
Then we defined a class whose name Derived
inherits from the class Base
only to warn you of the error that may appear if you try to inherit from a fixed class.
second example
#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.
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 Base
because it is a fixed class.
In the following example, we have defined a fixed class whose name Base
contains a function whose name isfunc()
.
Then we create an object from it and call the function in it.
third example
#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