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.
Related
I have a problem with a final function. I want to "stop" the polymorphism in a class but I still want to generate the same function in a derived class.
Something like this:
class Base{
protected:
int _x, _y;
public:
Base(int x = 0, int y = 0) : _x(x), _y(y){};
int x() const { return _x; }
int y() const { return _y; }
virtual void print()const{ cout << _x*_y << endl; }
};
class Derived : public Base{
public:
Derived(int x = 0, int y = 0) : Base(x, y){}
void print()const final { cout << _x*_y / 2.0 << endl; } // final inheritance
};
class NonFinal : public Derived{
void print()const{ cout << "apparently im not the last..." << endl }
// here i want a new function. not overriding the final function from Derived class
};
I think this is an experimental question, since actually you should rethink what you are doing when you require to "override a final function" (sounds contradicting, doesn't it?).
But you could introduce a "dummy"-parameter, i.e. void NonFinal::print(int test=0)const, which let's the compiler treat the member function as a different one. Not sure if that solves your "problem"; but at least it introduces a function with the same name, which can still be called without passing an argument, and which is separated from the ones of Derived and Base.
class NonFinal : public Derived{
public:
void print(int test=0)const{ cout << "apparently im not the last..." << endl; }
};
int main() {
Base b (10,10);
Derived d (20,20);
NonFinal nf;
Base *bPtr = &d;
bPtr->print(); // gives 200
bPtr = &nf; // gives 0
bPtr->print();
nf.print(); // gives "apparantly..."
}
Sorry, but it's not possible to create a function in a derived class when a function with the same name exists as final in the base class. You'll need to rethink your design.
The problem stems from the fact that a function declaration in a derived class with the same name as a function in a base class is treated as an attempt to override whether the override keyword is present or not (for historical reasons, I presume). So you can't "turn off" overriding.
Here's a relevant standard quote:
§ 10.3/4 [class.virtual]
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. [ Example:
struct B {
virtual void f() const final;
};
struct D : B {
void f() const; // error: D::f attempts to override final B::f
};
—end
#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'; }
};
I have a diamond design currently, and I saw a related question here
In that question, let me assume that class B and class C are virtual inherited from Class A, so in Class D, when we need to call virtual functions, we need to specify which one needed to call.
D::foo()
{
B::foo(); //specify foo() in B
}
For my diamond design, I have a lot of virtual functions to rewrite, in order to let these functions called by correct B or C father class functions.
It is not good, a lot of repeated work need to be done, when I have child class, do you have some better solutions, so that I can call foo() of B in class D but no rewrite for the example above.
Since C++11, you can do an aliasing:
class A
{
public:
virtual void foo() { cout << "A" << endl; }
}
class B : public virtual A
{
public:
void foo() { cout << "B" << endl; }
}
class C : public virtual A
{
public:
void foo() { cout << "C" << endl; }
}
class D : public B, C
{
using B::foo;
}
This way, doin:
D obj;
obj.foo();
Will output B;
I think template classes might do the trick here.
http://www.cplusplus.com/doc/tutorial/templates/
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?
I am learning about virtual functions and virtual tables in C++. But, I could not understand why there is a need for dynamic binding. Doesn't the compiler have all the information to figure out if the function call is for the derived or the base function, for example here:
class Base1 {
public : virtual void foo()
{ cout << " Base foo \n"; }
};
class Base2 {
public : virtual void foo()
{ cout << " Base2 foo \n"; }
};
class derived : public base1, base 2 {
public : virtual void foo()
{ cout << " derived foo \n"; }
}
int main()
{
derived d;
Base2 *p = &d;
p->foo(); // why can't the compiler figure out that this
// is a function call to the derived function
// foo at compile time?
return 0;
}
why cant compile figure that this is a function call to derived function foo during compile runtime itself?
It can. And some compilers will convert that call to static binding.
And there are other scenarios when the compiler must use dynamic binding.
Which foo() should get called in this function?
void function( Base* p )
{
p->foo();
}
It can't be determined*. Dynamic binding must be used.
*Edit: Based on the information I've given. :)