Overloaded function in derived class with Polymorphism (C++) - 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.

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.

Method Overriding 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.

Does final imply override?

As I understand it, the override keyword states that a given declaration implements a base virtual method, and the compilation should fail if there is no matching base method found.
My understanding of the final keyword is that it tells the compiler that no class shall override this virtual function.
So is override final redundant? It seems to compile fine. What information does override final convey that final does not? What is the use case for such a combination?
final does not require the function to override anything in the first place. Its effect is defined in [class.virtual]/4 as
If a virtual function f in some class B is marked with the
virt-specifier final and in a class D derived from B a function D::f
overrides B::f, the program is ill-formed.
That's it. Now override final would simply mean
„This function overrides a base class one (override) and cannot be overriden itself (final).“
final on it's own would impose a weaker requirement.
override and final have independent behavior.
Note that final can only be used for virtual functions though - [class.mem]/8
A virt-specifier-seq shall appear only in the declaration of a
virtual member function (10.3).
Hence the declaration
void foo() final;
Is effectively the same as
virtual void foo() final override;
Since both require foo to override something - the second declaration by using override, and the first one by being valid if and only if foo is implicitly virtual, i.e. when foo is overriding a virtual function called foo in a base class, which makes foo in the derived one automatically virtual. Thus override would be superfluous in declarations where final, but not virtual, occurs.
Still, the latter declaration expresses the intent a lot clearer and should definitely be preferred.
final does not necessarily imply that the function is overridden. It's perfectly valid (if of somewhat dubious value) to declare a virtual function as final on its first declaration in the inheritance hierarchy.
One reason I can think of to create a virtual and immediately final function is if you want to prevent a derived class from giving the same name & parameters a different meaning.
(Skip to the end to see the conclusion if you're in a hurry.)
Both override and final can appear only in declaration in a virtual function. And both key words can be used in the same function declaration, but whether it is useful to use them both depends on situations.
Take the following code as an example:
#include <iostream>
using std::cout; using std::endl;
struct B {
virtual void f1() { cout << "B::f1() "; }
virtual void f2() { cout << "B::f2() "; }
virtual void f3() { cout << "B::f3() "; }
virtual void f6() final { cout << "B::f6() "; }
void f7() { cout << "B::f7() "; }
void f8() { cout << "B::f8() "; }
void f9() { cout << "B::f9() "; }
};
struct D : B {
void f1() override { cout << "D::f1() "; }
void f2() final { cout << "D::f2() "; }
void f3() override final { cout << "D::f3() "; } // need not have override
// should have override, otherwise add new virtual function
virtual void f4() final { cout << "D::f4() "; }
//virtual void f5() override final; // Error, no virtual function in base class
//void f6(); // Error, override a final virtual function
void f7() { cout << "D::f7() "; }
virtual void f8() { cout << "D::f8() "; }
//void f9() override; // Error, override a nonvirtual function
};
int main() {
B b; D d;
B *bp = &b, *bd = &d; D *dp = &d;
bp->f1(); bp->f2(); bp->f3(); bp->f6(); bp->f7(); bp->f8(); bp->f9(); cout << endl;
bd->f1(); bd->f2(); bd->f3(); bd->f6(); bd->f7(); bd->f8(); bd->f9(); cout << endl;
dp->f1(); dp->f2(); dp->f3(); dp->f6(); dp->f7(); dp->f8(); dp->f9(); cout << endl;
return 0;
}
The output is
B::f1() B::f2() B::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() D::f7() D::f8() B::f9()
Compare f1() and f6(). We know that override and final is indepent sematically.
override means the function is overriding a virtual function in its base class. See f1() and f3().
final means the function cannot be overrided by its derived class. (But the function itself need not override a base class virtual function.) See f6() and f4().
Compare f2() and f3(). We know that if a member function is declared without virtual and with final, it means that it already override a virtual function in base class. In this case, the key word override is redundant.
Compare f4() and f5(). We know that if a member function is declared with virtualand if it is not the first virtual function in inheritance hierarchy, then we should use override to specify the override relationship. Otherwise, we may accidentally add new virtual function in derived class.
Compare f1() and f7(). We know that any member function, not just virtual ones, can be overridden in derived class. What virtual specifies is polymorphism, which means the decision as to which function to run is delayed until run time instead of compile time. (This should be avoid in practice.)
Compare f7() and f8(). We know that we can even override a base class function and make it a new virtual one. (Which means any member function f8() of class derived from D will be virtual.) (This should be avoid in practice too.)
Compare f7() and f9(). We know that override can help us find the error when we want to override a virtual function in derived class while forgot to add key word virtual in base class.
In conclusion, the best practice in my own view is:
only use virtual in declaration of the first virtual function in base class;
always use override to specify override virtual function in derived class, unless final is also specified.
The following code (with the final specifier) compiles. But compilation fails when final is replaced with override final. Thus override final conveys more information (and prevents compilation) than just final.
class Base
{
public:
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual void foo() final
{
std::cout << "in Derived foo\n";
}
};
Essentially, override final says this method cannot be overridden in any derived class and this method overrides a virtual method in a base class. final alone doesn't specify the base class overriding part.
No final does not necessarily imply override. In fact, you could declare a virtual function that you immediately declare final see here. The final keyword simply states that no derived class can create an override of this function.
The override keyword is important in that it enforces that you are indeed actually overriding a virtual function (instead of declaring a new unrelated one). See this post regarding override
So long story short, they each serve their own particular purpose, and it is often correct to use both.

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.