Difference between using virtual functions and redefining - c++

What's the difference between redefining and using a virtual function? Don't they serve the same purpose? You are allowing objects of a derived class to call their own versions of a function by the same name in both cases..so where is the distinction?

An example says it best:
#include <iostream>
using namespace std;
class A {
public:
virtual void f1() { cout << "Class A" << endl; }
void f2() { cout << "Class A" << endl; }
virtual ~A(){}
};
class B : public A {
public:
virtual void f1() { cout << "Class B" << endl; }
void f2() { cout << "Class B" << endl; }
virtual ~B(){}
};
int main()
{
A *a = new B;
a->f1();
a->f2();
}
...
$ ./override
Class B
Class A
You can see that when we reference the instance of B, f1() still calls B's version, but f2() calls A's.
When you declare a function virtual, you are saying that when we call it we should use the vtable to look up the right version of the function to call, and so you will always get the most derived version of the function, even if you reference it as an ancestor type. Without virtual, it will simply use the definition in the type you are referencing it as.

The distinction is when you have a reference or pointer to the base class. A call to a virtual function will call the most-derived version while a call to a normal function will call the base-class version.
If you're using a variable directly or a reference or pointer to the most-derived class, there is no practical difference.

TL;DR
The only way to take advantage of the polymorphism in C++ is via virtual functions and pointers (and references). The virtual keyword will tell the compiler to allocate a virtual function table where to look when deciding what version of the virtual function to call when dealing with pointer to the base class with a dynamic type that is of a child class.
How does polymorphism work in C++
Let's take a simple example:
class A { public: virtual void eat() { std::cout << "Class A" << std::endl; }
class B : public A {};
class C : public B { virtual void eat() { std::cout << "Class C" << std::endl; }
Note: the virtual keyword could be omitted after the first function/method definition.
The following:
A a; B b; C c;
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
ptrA->eat();
ptrB->eat();
ptrC->eat();
will print:
Class A
Class A
Class C
If we wouldn't have declared the function eat virtual, the output would have simply been:
Class A
Class A
Class A

But why
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
Instead of
A* ptrA = &a; B* ptrB = &b; C* ptrC = &c;
With the second version, the eat() method can simply be redefined for each derived class, without the need for virtual, right?

Related

Pointer to a base virtual member function

Is there a way to make a pointer on member function in base class if it is a virtual function and it is overridden in derived class?
Consider the code as follows
#include <iostream>
#include <functional>
struct Base
{
virtual void g() const
{
std::cout << "Base" << std::endl;
}
};
struct Derived : Base
{
virtual void g() const override
{
std::cout << "Derived" << std::endl;
}
};
int main()
{
Derived d;
(d.*(&Base::g))();
std::mem_fn(&Base::g)(d);
return 0;
}
It prints ‘Derived’ twice despite I make a pointer on Base::g. Is there a way to keep function g virtual and overridden and get member function pointer that will print ‘Base’ for d?
Just call the base function
int main()
{
Derived d;
d.g();
Base* b = &d;
b->Base::g();
//or
d.Base::g();
//or
auto callLater = [&d]() { d.Base::g();};
callLater();
return 0;
}
Output
Derived
Base
Base
Base
This can be made a pointer to the function; but it needs be to the member function Base::g() of the object being pointed to.
You might define a non-virtual function real_g called from g so code
struct Base
{
void real_g() const {
std::cout << "Base" << std::endl;
}
virtual void g() const { real_g(); };
};
Then later in main
std::mem_fn(&Base::real_g)(d);
See wikipage on virtual method table, this C++ reference and the C++ standard n3337 or better. Read also a good C++ programming book and the documentation of your C++ compiler, e.g. GCC
See also this answer (explaining naively what are vtables, in simple cases)

explanation on simple c++ inheritance

#include <iostream>
using namespace std;
class A {
public:
void m1(){ cout << 'A'; }
virtual void m2(){ cout << 'B'; }
virtual void m3(){ cout << 'C'; }
};
class B: public A {
public:
void m1(){ cout << 'D'; }
void m2(){ cout << 'E'; }
};
class C: public B {
public:
void m3(){ cout << 'F'; }
};
int main()
{
cout << "Hello World!" << endl;
A* a = new B();
a->m1();
a->m2();
a->m3();
return 0;
}
What will be the output? I initially thought that it will be "D E C" but after running the program it was "A E C"
Could one elaborate what is going on behind this line of code:
A* a = new B();
Virtual member functions are dispatched based on the dynamic (run-time) type of the object. Non-virtual member functions are dispatched based on the static (compile-time) type of the object.
A *a = new B();
a points to an object whose dynamic type is B. The static type of a is A*, however, which means that the static type of *a is A.
Virtual functions (m2 and m3) are dispatched based on the dynamic type, so B::m2 and B::m3 are called.
Non-virtual functions are dispatched based on the static type. The static type of *a is A, so A::m1 is called.
What exactly is going on in the new line? A new object of type B is created dynamically, and the new expression returns a pointer to that object (of type B*). Then, a derived-to-base conversion is applied to that pointer to convert it to an A*, which is used to initialise the variable a.
In pseudo-code, showing intermediary steps:
B *tmp_b = new B(); // allocate and initialise B object
A *tmp_a = convert_derived_to_base(tmp_b);
A *a = tmp_a;
m1 method is not virtual in class A, it can not be override .m2 is virtual so it override with class B method .
Here Class A is your parent class, so to override parent class's method you need to make it virtual in class A. So that Class B's method will be called. Please see more information on Virtual Functions
The output will be
AEC
The reason is that A::m1 was not declared virtual. In this line
A* a = new B();
You are declaring an A* variable named a, which is actually an instance of the derived class B. This is allowed because "B is a type of A".
When a function is declared virtual, if a derived class defines that function then the one in the base class is overridden with the version in the derived class. So the following calls will be made
a->m1(); // A::m1
a->m2(); // B::m2
a->m3(); // A::m3
void m1(){ cout << 'A'; }
virtual void m2(){ cout << 'B'; }
virtual void m3(){ cout << 'C'; }
The output is totally fine as per your programs code.
void m1(){ cout << 'A'; is not a virtual function.
So a->m1(); calls the base version of m1 and gives the o/p as A.
m2() is a virtual function and it has a new implementation inside class B.
void m2(){ cout << 'E'; }
So a->m2(); calls the class B version of the m2 function and gives the output E.
There is no new implementation of m3 inside class B.
So a->m3(); calls m3 which is inherited from class A.
To get the o/p as DEC you have to just change the m1 function to a virtual function like below
class A {
public:
virtual void m1(){ cout << 'A'; }
virtual void m2(){ cout << 'B'; }
virtual void m3(){ cout << 'C'; }
};

Strange behavior with virtual functions

With the following code, I would expect output to be B.f B.f DD.f, but instead the output I get is B.f B.f B.f. How is that possible, when DD derives from D which has f as virtual.
class B
{
public:
void f() { cout << "B.f "; }
};
class D : public B
{
public:
virtual void f() { cout << "D.f "; }
};
class DD : public D{
public:
virtual void f() { cout << "DD.f "; }
};
B * b = new B();
B * d = new D();
B * dd = new DD();
b->f();
d->f();
dd->f();
Functions become virtual from the level they were declared virtual up. You first declare f virtual in D, which means the dynamic dispatch will only happen from D upwards. B doesn't, nor should it know about the deriving classes.
Think about how the compiler sees it:
You have a pointer to B - B has the following definition:
class B
{
public:
void f() { cout << "B.f "; }
};
Since f is not virtual, I'll just go ahead and resolve the call statically - i.e. B::f().
For dynamic dispatch to work from a pointer to B, you need to make f() virtual in B:
class B
{
public:
virtual void f() { cout << "B.f "; }
};
You need to set B::f() to virtual, without set B::f() to virtual, it won't appear in B virtual table(vtbl), thus B::f() is called instead of dispatch the call to derived class.
class B
{
public:
virtual void f() { cout << "B.f "; }
};
As soon as you declare f() virtual in B,this starts to maintain a virtual table that holds the function pointers of all the other functions of same name of derived classes. This is a lookup table that is used to resolve function calls in a dynamic/late binding manner.
When you use a reference or a pointer to call a method, the compiler searches in the type of the pointer or reference at the declaration of the method (here it searches in B the declaration of some method with signature f()). When it finds one :
if it is NOT marked as virtual, then it solves it as a call to the method defined for this class - this is a static binding.
if it is marked as virtual, then the method called will be the appropriate one of the object referenced or pointed by - this is a dynamic binding.
The next test would have been :
DD * dd = new DD();
D * d = dd;
B * b = d;
b->f();
d->f();
dd->f();
One single object new DD() that is used/viewed differently... Each type can be thought as a kind of view you have on an object. If you see it as a B then f() does something but always the same thing, but if you see it as D or DD, f() does something different...
If you meet someone in the street, the standard way for him to salute you is to say hello, but for the same person, when he meets a friend of him he can either say hi! or Yo! :
class Person {
public:
void salute() { cout << "Hello" << endl; }
};
class Friend : public Person {
public:
virtual void salute() { cout << "Hi!" << endl; }
};
class RoomMate : public Friend {
public:
virtual void salute() { cout << "Yo!" << endl; }
};
void asACustomer(Person &p) {
p.salute(); // static binding, we need the standard politeness
}
void asAFriend(Friend &f) {
p.salute(); // dynamic binding, we want an appropriate message...
}
RoomMate joe;
asCustomer(joe);
asFriend(joe);
With static binding you know at compile time which method is called; with dynamic binding you cannot, you only know that an appropriate one will be. This is a key point in sub-typing polymorphism.
In general, be careful when mixing static and dynamic binding for a method.

converting pointer to base object into pointer of derivate class

I've been confused by the converting a pointer to base class object into pointer of derivate class.
Please check the following code:
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
The result is:
I'm a virtual function in base.
I'm a function in derivate class.
Can anyone help me explain why d1->print() print "I'm a virtual function in base."?
#include <iostream>
using namespace std;
class base
{
public:
virtual void print()
{
cout << "I'm a virtual function in base." << endl;
}
};
class derivate_class : public base
{
public:
void print()
{
cout << "I rewrite the virtual function in base." << endl;
}
void print1()
{
cout << "I'm a function in derivate class." << endl;
}
};
int main()
{
base* b = new base();
derivate_class *d = new derivate_class();
b->print();
d->print1();
base* cb = b;
b = d;
b->print();
cout << "*********************" << endl;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
system("pause");
return 0;
}
It's UB, so anything can happen.
But here's an explanation: d1 doesn't actually point to a derivate_class, but to a base.
base* b = new base();
//...
base* cb = b;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
The call is resolved dynamically because it's through a pointer and the method is virtual.
print1 isn't virtual so the call is resolved statically. print however is virtual, so the implementation in the most derived type is called. But the most derived type is actually base in this case.
Under the hood, the method print is looked for in the virtual function table that the vfptr in cb points to. Since cv is a base, the table will be that of base, which contains the function print with the base::print implementation. That's why that's the function getting called.
d1 is a derivate_class pointer but the data it's actually pointing to (cb) is of type base. Since print() is virtual, the call is resolved dynamically and so it will find base's implementation in the virtual function table instead of derivate_class's.

Can i use a method overriding a non-virtual method?

I am trying to understand a point here in C++.
If class A has a non-virtual method, and class B, which extends A, overrides that method, can i create an instance of B and somehow use the method defined in B?
Is there a point to override a non-virtual method?
Is there a point to override a non-virtual method?
You are not actually overriding, but this is the behavior, i.e
B* b = new B();
A* a = new B();
b->method(); //Calls B's method
a->method(); // Calls A's method
So, the pointer/reference type determines the method called.
can i create an instance of B and somehow use the method defined in B?
Yes. The pointer/reference type has to be of type B. (see previous example).
If you don't declare method to be virtual, you cannot override it, but you can hide it.
If B inherits from A, and redefines a method defined in A, then new instances of B will call B's version. However, if the method is not virtual, then there is no polymorphic behavior, so if an instance of B is referenced as an A, then the method will be A's. For example:
struct A {
void foo () { std::cout << "A::foo" << std::endl; }
};
struct B : public A {
void foo () { std::cout << "B::foo" << std::endl; }
};
B b;
b.foo();
A *a = &b;
a->foo();
The output of the code above would be:
B::foo
A::foo
However, if the foo method had been virtual, then B::foo would have been printed twice.
If a function is not virtual then the type of the variable determines which implementation is dispatched too:
#include <iostream>
using namespace std;
struct A {
void f() { cout << "A" << endl; }
};
struct B : public A {
void f() { cout << "B" << endl; }
};
int main(int args, char** argv) {
B b;
A& a = b;
b.f();
a.f();
return 0;
}
No, there is no mechanism to override a non-virtual method in class A.
Yes, you can use a non-virtual method from class A overloaded in B by using scope resolution operator A::methodName