#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'; }
};
Related
I didn't know what to give as a title, I expect more experienced stackoverflow.com users to improve it.
Let's say we have the class A
class A {
void hello(){ cout << "i'm an A" << endl; }
}
and its sub-class B
class B: public A {
void hello(){ cout << "i'm a B" << endl; }
}
Then we did somewhere in our program
A* array[2];
array[0] = new A;
array[1] = new B;
array[0]->hello(); // output: "i'm an A"
array[1]->hello(); // output: "i'm a B"
why doesn't the array[1].hello(); output I'm a B since we instanciated a B object for that base-class pointer ? and how to make it happen ?
Couple of changes here:
make function hello in class A, a virtual and public: because by default it is private
class A {
public:
virtual void hello(){ cout << "i'm an A" << endl; }
};
Similarly make hello in class B virtual
class B: public A {
virtual void hello(){ cout << "i'm a B" << endl; }
};
You have to make hello a virtual function:
class A {
virtual void hello() { cout << "i'm an A" << endl; }
};
class B : public A {
virtual void hello() override { cout << "i'm a B" << endl; } // 1)
};
This tells the compiler that the actual function should not be determined by the static type (the type of the pointer or reference) but by the dynamic (run-time) type of the object.
1) The overridekeyword tells the compiler to check, if the function actually overrides a hello function in the base class (helps e.g. to catch spelling mistakes or differences in the parameter types).
Since you have inherited class A in class B, derived class B will call the function from the Base class. You need to override the function in class B, as you want to change the Base class functionality.
You can do this with the override and virtual keywords.
http://en.cppreference.com/w/cpp/language/override
#include<iostream>
class A {
public:
void init(){
std::cout << "A" << std::endl;
}
};
class B: public A {
public:
void init(){
std::cout << "B" << std::endl;
}
};
int main() {
A *o = new B();
/*
Some codes here
*/
o->init();
return 0;
}
Result:
A
In the above program, the init called is of class A. How do I call the init function of class B?
edit: I need to call both the inits. I can't change the A and B class. And I have to make the object declaration like that in main.
Make the init() function virtual in Class A.
class A {
public:
virtual void init(){
std::cout << "A" << std::endl;
}
};
The object o has two parts. The base part and the derived part. If you want B::init() to be called from o, then you will have to tell the compiler that it is a virtual function and it should look for the function overload in the derived class.
I suggest you go through the tutorial on this website to learn more about inheritance:
http://www.learncpp.com/cpp-tutorial/113-order-of-construction-of-derived-classes/
You have some options here:
B *o = new B(); // in Main
or
(B *)o->init(); // in Main
or
virtual void init(){
std::cout << "A" << std::endl;
} // in Class A
b = dynamic_cast<B*>(o);
if(b!=NULL)
b->init();
this will call the function for object of type B.
make init function virtual
create a pointer of class A
create an object of class B
assign address of B object to pointer A
now access init function of B
since class B hides the definition of init() in its base-class, it will make the function sensitive to the type of any pointer or reference from which the function might be called.
And as you mentioned A and B are prewritten class, you can instantiate a pointer to class B, or cast to a pointer to class B.
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?
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.
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.