Method Overriding C++ - c++

I got a Question in my Exam which was this:
Function Overriding means the functions have the same prototype but
differ in their body
Justify the Statement with the help of an Example.
Now I quoted this code snippet as Example :
#include<iostream>
using namespace std;
class A {
public: virtual void print() {
cout << "I am Base Class's print Function" << endl;
}
};
class B: public A {
public: void print() {
cout << "I am Derived's Class print function" << endl;
}
};
Here I have made two classes, Class A and Class B and Class B is inheriting Class A. Now, by definition of Method Overriding, we mean that the Function which gets created in the Base Class gets overridden in the Derived Class.
I made the Function in the Base Class as a Virtual Function.
Now, my main() file:
int main() {
A * a1;
B b1;
a1 = & b1;
a1 - > print();
}
Now, I want to ask that is my above code snippet example for above question is right or not. I have performed Function Overriding at run time. In my main file, the Base Class Object is a Pointer that is having the Address of the Derived Class. When I will call print() function using a1, it will execute the print() function of the Derived Class.
So isn't my example justified? Am I right or not?

You could use the classical Cat vs Dog example where both classes inherit from a common base class, i.e. Animal. The common base class can then have a pure virtual function that is then overridden with a differing implementation (method body) in each subclass.
#include <iostream>
class Animal
{
public:
virtual ~Animal() = default;
virtual void MakeSound() const = 0;
};
class Dog : public Animal
{
public:
virtual void MakeSound() const override;
};
class Cat : public Animal
{
public:
virtual void MakeSound() const override;
};
void Dog::MakeSound() const
{
std::cout << "Woof!" << std::endl;
}
void Cat::MakeSound() const
{
std::cout << "Meow!" << std::endl;
}
int main()
{
const Dog dog{};
const Cat cat{};
const Animal& firstAnimal{dog};
const Animal& secondAnimal{cat};
/*
* These functions have the same prototype, void MakeSound(),
* but differ in their implementation.
*/
firstAnimal.MakeSound();
secondAnimal.MakeSound();
return 0;
}

If you teacher expected this as answer and considers your example as wrong then I would argue that they teach you overriding the wrong way.
From cppreference:
Virtual functions are member functions whose behavior can be overridden in derived classes.
Of course this does not strictly imply the reverse statement: "functions that can be overriden are virtual". But if this wasnt true, the quoted sentence would make little sense.
Non-virtual methods are not really meant to be overriden. From the C++ FAQ:
Should a derived class redefine (“override”) a member function that is non-virtual in a base class?
It’s legal, but it ain’t moral. [...]
Note that they put "override" in quotes, because strictly speaking it is not overriding but merely redefining.
Further, you can read on cpprefernce about the override specifier (emphasize mine):
In a member function declaration or definition, override ensures that the function is virtual and is overriding a virtual function from a base class. The program is ill-formed (a compile-time error is generated) if this is not true.
TL;DR If I had to judge I would consider this as a misleading bad example for overriding, while your code seems fine. It could benefit from using override and A should have a virtual destructor, but thats details.

Related

Operator<< in base class not visible in derived class [duplicate]

I am trying to understand why the following code does not compile, apparently the solution relies in specifically declaring the dependency on method_A in the derived class.
Please refer to the following code:
class Base
{
public:
void method_A(int param, int param2)
{
std::cout << "Base call A" << std::endl;
}
};
//does not compile
class Derived : public Base
{
public:
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
//compiles
class Derived2 : public Base
{
public:
using Base::method_A; //compile
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
int main ()
{
Derived myDerived;
myDerived.method_A(1);
myDerived.method_A(1,2);
Derived2 myDerived2;
myDerived2.method_A(1);
myDerived2.method_A(1,2);
return 0;
}
"test.cpp", (S) The wrong number of arguments have been specified for "Derived::method_A(int)".
What is the technical reason that prevents the derived class to know its base class is implementing the method it's trying to overload?
I am looking in understanding better how the compiler/linker behaves in this case.
Its called Name Hiding. When you define a non virtual method with the same name as Base method it hides the Base class method in Derived class so you are getting the error for
myDerived.method_A(1,2);
To avoid hiding of Base class methods in Derived class use using keyword as you did in Derived2 class.
Also if you want to make it work you can do it explictly
myDerived.Base::method_A(1,2);
Check out this for better explanation why name hiding came into picture.
Well, for one you're calling
myDerived.method_A(1,2);
with 2 arguments, whereas both in base and derived the method is declared to take only one argument.
Secodnly, you're not overriding anything, because method_A is not virtual. You're overloading.
If your intention is to override void Base::method_A(int param, int param2) then you should mark it virtual in the base class:
virtual void method_A(int param, int param2)
Any function overriding this must have the same parameters and almost the same return type ('almost' loosely meaning that the differing return types must be polymorphically related, but in most cases it should have the identical return type).
All you're currently doing is overloading the function in the base class. The using keyword is bringing the base class function into the child class' namespace, as the language behaviour is not to do this by default.

Overloaded function in derived class with Polymorphism (C++)

Considering this code example:
#include <iostream>
using namespace std;
class Base
{
private:
int number;
public:
Base():number(10){}
~Base(){}
virtual void print()
{
cout << "Base class" << endl;
}
};
class Derived : public Base
{
public:
Derived():Base(){}
~Derived(){}
void print(int value)
{
//printing number in Base class and paramter value
cout << "Derived with value " << value << " number is" << number << endl;
}
};
I wanted to use polymorphism and call theoverloaded print() function.
So use these classes as follows:
void somewhere_else()
{
Base* polymorphism = new Derived();
polymorphism->print(5); //Error indicating there are too many parameter
//thinking that I am trying to use print in Base class
((Derived*)polymorphism)->print(5)
//This works as I am casting the variable as Derived variable
}
Unfortunately, I can't call print() from the base class pointer (compilation error, see comment above). I can only call it with a cast.
Is there a better way to keep the polymorphism and still calls overloaded function based on derived class?
In your code you have two different member functions, that have different signatures:
a virtual print() that takes no argument. It is declared and defined in Base, and inherited in Derived
a non-virtual print() that takes one int argument. It is declared and defined ONLY for Derived
So the base object doesn't know a print function with an int parameter. This is why you need to cast (which is by the way a symptom that should ring alarm bells if you need it).
How to improve ?
First, if you want to override a virtual function in a derived class, use the keyword override:
class Derived : public Base
{
public:
Derived():Base(){}
~Derived(){}
void print(int value) override
{
...
}
};
This will ensure an error message in case of subtle mismatch in the function signature:
prog.cpp:23:10: error: ‘void Derived::print(int)’ marked ‘override’, but does not override
void print(int value) override
^~~~~
Then make sure that the signatures are aligned in the base class and derived class (i.e. either both take an int argument or non of them.
Note that you can't access a private member of the base class in a derived class. You have to define number as protected to print it in Derived.
Finally, if you have a base class having a virtual member, it is a sound practice to systematically make the destructor virtual. This will avoid subtle bugs for more complex classes:
class Base
{
protected:
int number;
public:
Base():number(10){}
virtual ~Base(){}
virtual void print(int value)
{
...
}
};
Here the online demo
Now that the things are working, here a short article making the difference between overload and override.

Virtual keyword use in C++

I understand that C++ implements runtime polymorphism thorugh virtual functions and that virtual keyword is inherited but I don't see use of virtual keyword in derived class.
e.g. In below case even if you dropped virtual keyword in derived class still ptr->method() call goes to derived::method. So what extra this virtual keyword is doing in derived class?
#include<iostream>
using namespace std;
class base
{
public:
virtual void method()
{
std::cout << std::endl << "BASE" << std::endl;
}
};
class derived: public base
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED" << std::endl;
}
};
int main()
{
base* ptr = new derived();
ptr->method();
return 9;
}
If the method of the derived class matches a virtual method of one of the base classes by name and signature, and the matched method is virtual, then the method of a derived class becomes virtual as well. So, technically, there is no need to mark such methods as «virtual» in derived classes. However, before C++11 it used to be a good practice just because it is a great hint to those reading the code (it could be hard to keep in mind all of the virtual functions of base class(es)).
Starting with C++11, there are two additional keywords for doing this in the derived classes that help both readability and code robustness. They are «override» and «final». For example, putting «override» in a derived class`s method ensures that a corresponding method of a base class is, in fact, virtual. The «final» keyword does the same plus it prevents the method from being further overriden.
I also wrote about this with more real-world rationales and code examples in my blog, here.
Hope it helps. Good Luck!
Nothing. Just to help remind you what functions are virtual or not.
virtual is only necessary in the base class declaration. It's optional in the derived class(es), and probably serves mostly as a reminder in those cases.
C++11 introduces override to make things even more explicit : it explicitely marks a method in a derived class as being an override of a virtual method of a base class.
Implicitly virtual methods in derived classes are virtual in derived classes, no need to explicitly define them virtual.If you declare it will be redundant declaration.
ptr->method();
When the compiler came across the above statement
-> It will try to resolve the above statement, as the method() function is virtual, compiler postpone the resolving of that call to run time.
->As you created the object of derived class at run time, now the compiler will get to know that this method is of derived class.
what extra this virtual keyword is doing in derived class?
Consider this scenario there is one more derived class called Derived2 inherting form derived and it has its own virtual method.
class derived2: public derived
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED2" << std::endl;
}
};
If you call the method() in main like below
int main()
{
base* ptr = new derived2();
ptr->method(); //derived2 class method() will get called
return 9;
}
If the method() in derived2 is not virtual by default, you will end up calling teh derived version of method(), loosing the benefit of runtime polymorphism.
Hence the authors of c++ did a wonderful job here, by making the virtual key word inheritance hierarchical.
virtual keyword is optional in drive class because according to the rule when you drive a class with the base class which have virtual function and when you override the virtual function in drive class compiler implicitly assign virtual keyword along with the function. So you not need to explicitly assign the virtual keyword. But this keyword is necessary during multilevel inheritance.
Example:
In your code we add this code.
class derived: public base {
public:
virtual void method() { // In this line virtual keyword is optional.
std::cout << std::endl << "DERIVED :: method function" << std::endl;
}
virtual void display() {
std::cout << std::endl << "DERIVED :: display function" << std::endl;
}
};
class deriveChild: public derived {
public:
void method() {
std::cout << std::endl << "DERIVECHILD :: method" << std::endl;
}
void display() {
std::cout << std::endl << "DERIVECHILD:: display" << std::endl;
}
};
In the main() if you use below code it will give you different output.
base *ptr = new deriveChild();
ptr->method(); // will compile and execute
ptr->display(); // will generate error because display() is not part of base class.
Now if you want to use display() of deriveChild class then use this code.
derived *ptr = new deriveChild();
ptr->method(); // Compile and Execute
ptr->display(); // Compile and Execute

overloading base class method in derived class

I am trying to understand why the following code does not compile, apparently the solution relies in specifically declaring the dependency on method_A in the derived class.
Please refer to the following code:
class Base
{
public:
void method_A(int param, int param2)
{
std::cout << "Base call A" << std::endl;
}
};
//does not compile
class Derived : public Base
{
public:
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
//compiles
class Derived2 : public Base
{
public:
using Base::method_A; //compile
void method_A(int param)
{
std::cout << "Derived call A" << std::endl;
}
};
int main ()
{
Derived myDerived;
myDerived.method_A(1);
myDerived.method_A(1,2);
Derived2 myDerived2;
myDerived2.method_A(1);
myDerived2.method_A(1,2);
return 0;
}
"test.cpp", (S) The wrong number of arguments have been specified for "Derived::method_A(int)".
What is the technical reason that prevents the derived class to know its base class is implementing the method it's trying to overload?
I am looking in understanding better how the compiler/linker behaves in this case.
Its called Name Hiding. When you define a non virtual method with the same name as Base method it hides the Base class method in Derived class so you are getting the error for
myDerived.method_A(1,2);
To avoid hiding of Base class methods in Derived class use using keyword as you did in Derived2 class.
Also if you want to make it work you can do it explictly
myDerived.Base::method_A(1,2);
Check out this for better explanation why name hiding came into picture.
Well, for one you're calling
myDerived.method_A(1,2);
with 2 arguments, whereas both in base and derived the method is declared to take only one argument.
Secodnly, you're not overriding anything, because method_A is not virtual. You're overloading.
If your intention is to override void Base::method_A(int param, int param2) then you should mark it virtual in the base class:
virtual void method_A(int param, int param2)
Any function overriding this must have the same parameters and almost the same return type ('almost' loosely meaning that the differing return types must be polymorphically related, but in most cases it should have the identical return type).
All you're currently doing is overloading the function in the base class. The using keyword is bringing the base class function into the child class' namespace, as the language behaviour is not to do this by default.

Question on Virtual and default arguments

I wanted to have confirmation about the following things:
Virtual Mechanism:
I f I have a base class A and it has a Virtual method, then in the derived class generally, we do not include the virtual statement in the function declaration. But what does a virtual mean when included at the dervied class definition.
class A
{
public:
virtual void something();
}
class B:public A
{
public:
virtual void something();
}
Does, that mean that we want to override the method somethign in the classes that derive from the class B?
Also, another question is,
I have a class A, which is derived by three different classes.Now, there is a virtual method anything(), in the base class A.
Now, if I were to add a new default argument to that method in the base class, A::anything(), I need to add it in all the 3 classes too right.
My pick for the answers:
If a method which is virtual in the base class is redefined in the derived class as virtual then we might mean that it shall be overridden in the corresponding derived classes which uses this class as base class.
Yes.If not overriding does not have any meaning.
Pls let me know if what I feel(above 2) are correct.
Thanks,
Pavan Moanr.
The virtual keyword can be omitted on the override in the derived classes. If the overridden function in the base class is virtual, the override is assumed to be virtual as well.
This is well covered in this question: In C++, is a function automatically virtual if it overrides a virtual function?
Your second question is about default values and virtual functions. Basically, each override can have a different default value. However, usually this will not do what you expect it to do, so my advice is: do not mix default values and virtual functions.
Whether the base class function is defaulted or not, is totally independent from whether the derived class function is defaulted.
The basic idea is that the static type will be used to find the default value, if any is defined. For virtual functions, the dynamic type will be used to find the called function.
So when dynamic and static type don't match, unexpected results will follow.
e.g.
#include <iostream>
class A
{
public:
virtual void foo(int n = 1) { std::cout << "A::foo(" << n << ")" << std::endl; }
};
class B : public A
{
public:
virtual void foo(int n = 2) { std::cout << "B::foo(" << n << ")" << std::endl; }
};
int main()
{
A a;
B b;
a.foo(); // prints "A::foo(1)";
b.foo(); // prints "B::foo(2)";
A& ref = b;
ref.foo(); // prints "B::foo(1)";
}
If all your overrides share the same default, another solution is to define an additional function in the base class that does nothing but call the virtual function with the default argument. That is:
class A
{
public:
void defaultFoo() { foo(1); }
virtual void foo(int n) { .... }
};
If your overrides have different defaults, you have two options:
make the defaultFoo() virtual as well, which might result in unexpected results if a derived class overload one but not the other.
do not use defaults, but explicitly state the used value in each call.
I prefer the latter.
It doesn't matter whether you write virtual in derived class or not, it will always be virtual because of the base class, however it is still better to include virtual to explicitly state that it is virtual and then if you accidentally remove that keyword from base class it will give you compiler error (you cannot redefine non-virtual function with a virtual one). EDIT >> sorry, I was wrong. You can redefine non-virtual function with a virtual one however once it's virtual all derived classes' functions with same signature will be virtual too even if you don't write virtual keyword. <<
If you don't redefine virtual function then the definition from base class will be used (as if it were copied verbatim).
If you wish to specify that a virtual function should be redefined in dervied class you should not provide any implementation i.e. virtual void something() = 0;
In this case your class will be an abstract base class (ABC) and no objects can be instantiated from it. If derived class doesn't provide it's own implementetian it will also be an ABC.
I'm not sure what do you mean about default arguments but function signatures should match so all parameters and return values should be the same (it's best to not mix overloading/default arguments with inheritance because you can get very surprising results for example:
class A
{
public:
void f(int x);
};
class B:public A
{
public:
void f(float x);
};
int main() {
B b;
b.f(42); //this will call B::f(float) even though 42 is int
}
Here is a little experiment to test out what you want to know:
class A {
public:
virtual void func( const char* arg = "A's default arg" ) {
cout << "A::func( " << arg << " )" << endl;
}
};
class B : public A {
public:
void func( const char* arg = "B's default arg" ) {
cout << "B::func( " << arg << " )" << endl;
}
};
class C : public B {
public:
void func( const char* arg ) {
cout << "C::func( " << arg << " )" << endl;
}
};
int main(int argc, char* argv[])
{
B* b = new B();
A* b2 = b;
A* c = new C();
b->func();
b2->func();
c->func();
return 0;
}
result:
B::func( B's default arg )
B::func( A's default arg )
C::func( A's default arg )
conclusion:
1- virtual keyword before A's func declaration makes that function virtual in B and C too.
2- The default argument used is the one declared in the class of pointer/reference you are using to access the object.
As someone pointed out, a function in a derived class with the same name and type signature as a virtual function in the base class is automatically always a virtual function.
But your second question about default arguments is interesting. Here is a tool for thinking through the problem...
class A {
public:
virtual void do_stuff_with_defaults(int a = 5, char foo = 'c');
};
is nearly equivalent to this:
class A {
public:
virtual void do_stuff_with_defaults(int a, char foo);
void do_stuff_with_defaults() { // Note lack of virtual keyword
do_stuff_with_defaults(5, 'c'); // Calls virtual function
}
void do_stuff_with_defaults(int a) { // Note lack of virtual keyword
do_stuff_with_defaults(a, 'c'); // Calls virtual functions
}
};
Therefore you are basically having virtual and non-virtual functions with the same name but different type signatures declared in the class if you give your virtual function default arguments.
On way it isn't equivalent has to do with being able to import names from the base class with the using directive. If you declare the default arguments as separate functions, it's possible to import those functions using the using directive. If you simply declare default arguments, it isn't.