Calling a virtual function from within an inherited function? - c++

I've tried to map it out in my head, but honestly I have no idea what's really going on here.
What exactly is happening when I add and remove the virtual keyword from the below example?
#include <iostream>
#include <string>
class A {
public:
A() { me = "From A"; }
void caller() { func(); }
virtual void func() { std::cout << me << std::endl; } // THIS LINE!
private:
std::string me;
};
class B : public A {
public:
B() { me = "From B"; }
void func() { std::cout << me << std::endl; }
private:
std::string me;
};
int main() {
A a;
a.caller();
B b;
b.caller();
return 0;
}
With the virtual keyword, it prints "From A", then "From B".
Without the virtual keyword, it prints "From A", then "From A".
So far, this is the only time I've found a use for virtual functions without pointers being involved. I thought that if the virtual keyword was removed, the compiler would do the standard thing which is to overload the inherited function and end up printing "From A", and "From B" anyway.
I think this is deeper than just the VTable, and that it's more about the way it behaves in particular circumstances. Does B even have a VTable?

The call
func()
is equivalent to
this->func()
so there is a pointer involved.
Still, there's no need to involve pointers to understand the behavior.
Even a direct call of e.g. b.func() has to work as if it's a virtual call, when func is virtual in the statically known type. The compiler can optimize it based on knowing the most derived type of b. But that's a different kind of consideration (optimizations can do just about anything).

Apart from the issue of virtual dispatch, what may bring extra confusion, is that you have two mes, one declared in A and another declared in B. These are two distinct objects.
An object of type B has two data members of type std::string; one on its own, and one incorporated into the subobject of type A. The latter one, though, is not immediately available in the methods of type B because its name is eclipsed by the new me introduced in this class (though you may use a qualified name, A::me to refer to it).
Therefore, even though the bodies of A::func and B::func seem identical, the identifier me used in both of them refers to different members.

In your example, you won't see the difference:
With the virtual function, the compiler will generate a call via the VTable and at runtime, each objects will call the right function for their real class.
With the non virtual function, the compiler determines at compile time the right function to call, based on the objects defined class.
Now try the following, to see the virtual function in action:
A *pa = &b; // pointer to an A: valid as b is a B wich is also an A.
pa -> caller(); // guess what will be called if virtual or not.
No need for pointer to experimenting with virtual functions. You can observe the same effect with references as well:
A& ra = b; // create a reference to an A, but could as well be a parameter passed by reference.
ra.caller();
Virtual functions are useful for polymorphism. The idea is that you work with a general object of a class, but you don't know at compile time, if at runtime the object will really be of this class, or if it will not be a more specialiszed object (inheriting from the class).

Related

pure virtual function with implementation in C++

I'm aware that one can make implementation for pure virtual function in base class, as a default implementation. But i don't quite understand the code below.
class A {
public:
virtual void f1() = 0;
virtual void f2() = 0;
};
void A::f1(){
cout << "base f1" << endl;
f2();
}
void A::f2(){
cout << "base f2" << endl;
}
class B: public A {
public:
void f1() { A::f1(); }
void f2() { cout << "derived f2" << endl; }
};
int main(){
B b;
b.f1();
}
Why does the B::f1() calls B::f2() instead of A::f2. I know it will behave this way, but why? what basic knowledge i have missed.
another question, did implementation for pure virtual function in base class make the pure(=0) unnecessary?
This is the behaviour the C++ standard defines for virtual functions: call the version of the most derived type available.
Sure, for normal objects, the most derived type is the one of the object itself:
B b;
b.f1(); // of course calls B's version
The interesting part is if you have pointers or references:
B b;
A& ar = b;
A* ap = &b;
// now both times, B's version will be called
ar.f1();
ap->f1();
The same occurs inside f1, actually, you do implicitly:
this->f2(); // 'this' is a POINTER of type A* (or A const* in const functions).
There's a phenomenon when this does not occur (the example below requires a copy constructor):
B b;
A a = b; // notice: not a pointer or reference!
A.f1(); // now calls A's version
What actually happens here is that only the A part of b is copied into a and the B part is dropped, so a actually is a true, non-derived A object. This is called 'object slicing' and is the reason for that you cannot use base objects in e. g. a std::vector to store polymorphic objects, but need pointers or references instead.
Back to virtual functions: If you are interested in the technical details, this is solved via virtual function tables, short vtables. Be aware that this is only a de-facto standard, C++ does not require implementation via vtables (and actually, other languages supporting polymorphism/inheritance, such as Java or Python, implement vtables, too).
For each virtual function in a class there's an entry in its corresponding vtable.
Normal functions are called directly (i. e. an unconditional branch to the function's address is executed). For virtual function calls, in contrast, we first need to lookup the address in the vtable and only then we can jump to the address stored there.
Derived classes now copy the vtables of their base classes (so initially these contain the same addresses than the base class tables), but replace the appropriate addresses as soon as you override a function.
By the way: You can tell the compiler not to use the vtable, but explicitly call a specific variant:
B b;
A& a = b;
a.A::f1(); // calls A's version inspite of being virtual,
// because you explicitly told so
b.A::f1(); // alike, works even on derived type

Confusion is memory allocation for pointers and virtual functions

I read about virtual functions but i am not able to clear the concept.
In the below mentioned example.We are creating a base pointer and assigning base object first and calling function is base class and later assigning derived object and calling its function. Since we have already mentioned which objects will be assigned does not compiler know which object function to call during compilation? I did not get why the decision will be delayed till run time. Am i missing something here.?
#include <iostream>
using std::cout;
using std::endl;
// Virtual function selection
class Base
{
public:
virtual void print() const
{
cout << "Inside Base" << endl;
}
};
class Derived : public Base
{
public:
// virtual as well
void print() const
{
cout << "Inside Derived" << endl;
}
};
int main()
{
Base b;
Derived f;
Base* pb = &b; // points at a Base object
pb->print(); // call Base::print()
pb = &f; // points at Derived object
pb->print(); // call Derived::print()
}
In your particular case, the compiler could potentially figure out the type of the objects being pointer at by the base class pointer. But the virtual dispatch mechanism is designed for situations in which you do not have this information at compile time. For example,
int n;
std::cin >> n;
Base b;
Derived d;
Base* pb = n == 42 ? &b : &d;
Here, the choice is made based on user input. The compiler cannot know what pb will point to.
Since we have already mentioned which objects will be assigned does not compiler know which object function to call during compilation? I did not get why the decision will be delayed till run time.
In this very specific, contrived case, your compiler can optimise out all the polymorphism, yes.
Am i missing something here.?
The imagination to realise that the vast majority of code in real life is not this simple. There are infinitely many C++ programs for which the compiler does not have enough information to perform this optimisation.
As per my understanding, the compiler will just look at the reference type at compile time and bind the function defined and declared in that class. Since the Derived -> print() should be called you have to make the print function virtual in the base class so that the compiler will delay the binding to run time and use the function defined in the derived class.
Due to the fact that it is virtual, it is able to dynamically bind the function to the correct object. This means that the pointer calling the function will call the referenced object's function.

when a base class pointer point to a base class object whether the compiler will use dynamic binding?

I know that when use a base class pointer which point to a derived class object to call a virtual function, the compiler will use dynamic binding to call the derived version.
But when use a base class pointer which point to a base class object to call a virtual function, does the compiler use dynamic binding or static binding to call the virtual
function?
For example:
class Base
{
public:
virtual void show()
{
cout << "base class";
}
}
int main()
{
Base *pb; //Base class pointer
Base b; //Base class object
pb = &b;
pb->show(); //Is static binding or dynamic binding?
}
Because My English is very bad, so I want to make my question as simple as possible, but I will describle my question in more detail in follow:
Actually the problem stems from that I am summarizing how to trigger dynamic binding.
At first I summary the trigger condition are:
the function must a virtual function.
must use pointer or reference to call the function.
The two trigger condition cause the problem that I asked:
"when a base class pointer point to a base class object whether the compiler will use dynamic binding?"
I have google for search answer, and I find a fragment (the demo is here):
struct A {
virtual void f() { cout << "Class A" << endl; }
};
struct B: A {
//Note that it not overrides A::f.
void f(int) { cout << "Class B" << endl; }
};
struct C: B {
void f() { cout << "Class C" << endl; }
};
int main() {
B b; C c;
A* pa1 = &b;
A* pa2 = &c;
// b.f();
pa1->f();
pa2->f();
}
The following is the output of the above example:
"Class A"
"Class C"
According to pa1->f() will output Class A, I summary third trigger condition:
3.function in base class must be overridden in the derived class.
Now according to the three trigger condition, when use a base class pointer which point to a base class object to call a virtual function, the compiler will use static binding to call the virtual function, because the virtual is not overridden.
But when use a derived class pointer which point to a derived class object to call a virtual function, it will use dynamic binding, because the virtual is overridden.
It made me very confused.
It can choose whichever, or neither, depending on how smart it is and how well it can detect. The rule is polymorphism must work. How this is achieved is an implementation detail.
If the same end-result can be achieved with both dynamic or static binding, as is the case here, both are valid options for the compiler.
In your case, the function doesn't have to be called at all - the generated code could be just as well identical to code generated by
int main()
{
cout << "base class";
}
I guess it depends on compiler optimization. Compiler might be clever enough to figure out that Base::show is always the one called or it might not. You can look at the disassembly to find out. You can force static-binding with b->Base::show()
Short answer: No. At least in theory not. Because in theory, the compiler does not know wether the pointer points to a Base, a Derived or to YetAnotherDerived object. Therefore it has to apply the same mechanism regardless of the dynamic type of the object.
But: In practise, compilers have optimizers, capable of identifying some use cases where the dynamic type is known. I your case it can detect the aliasing, meaning it knows that pb points to b and that it is a local variable and cannot be changed concurrently, so it knows that in fact you are calling b.show() and will abbreviate the output to reflect that fact and get rid of the virtual dispatch. Similar optimizations are possible e.g. in this code:
auto pb = make_unique<Base>();
pb->show();
But as any optimization it is up to the compiler if it applies them - the standard says virtual dispatch happens even if the pointer points to a Base object, and that's it.

Is it possible to call derived object's virtual method when down-casted from base class?

Given the following class structure:
class Base
{
virtual void outputMessage() { cout << "Base message!"; }
};
class Derived : public Base
{
virtual void outputMessage() { cout << "Derived message!"; }
}
.. and this code snippet:
Base baseObj;
Derived* convertedObj = (Derived*) &baseObj;
convertedObj->outputMessage();
.. the output will be "Base message!".
Is there any way to cast or manipulate the object to make Derived's version of the outputMessage method to be called polymorphically?
Edit: I will attempt to show the reason why I'm after this:
I am writing migration tools that hook into our main system. For this reason, I need to get access to protected member methods, or customise existing virtual methods. The former I can do by defining a derived class and casting objects to it, to call methods statically. What I can't do is change the behaviour for methods which I do not call statically (ie methods that are called elsewhere in the codebase).
I have also tried creating objects of the derived class directly, but this causes issues in other parts of the system due to the manipulation of the objects passed through the constructor.
No, virtual functions operate on the actual types of the object being pointed to, which in your case is just a simple Base.
Actually, with the down-casting, you're entering undefined-behaviour land here. This can blow off like a bomb with multiple inheritance, where the vtable in the derived class isn't at the same offset as the vtable in the base class.
No Standard-compliant solution
What you're trying to do isn't possible using behaviours guaranteed by the C++ Standard.
If you really MUST do this as a short-term measure to assist your migration, don't depend on it in production, and can adequately verify the behaviour, you could experiment as illustrated below.
Discussion of your attempt
What I'm showing is that you're taking the wrong approach: simply casting a pointer-to-base to a pointer-to-derived doesn't alter the object's vtable pointer.
Deriving a plausible hack
Addressing that, the naive approach is to reconstruct the object in place as a derived object ("placement" new), but this doesn't work either - it will reinitialise the base class members.
What you can possibly do is create a non-derived object that has no data members but the same virtual dispatch table entries (i.e. same virtual functions, same accessibility private/protected/public, same order).
More warnings and caveats
It may work (as it does on my Linux box), but use it at your own risk (I suggest not on production systems).
Further warning: this can only intercept virtual dispatch, and virtual functions can sometimes be dispatched statically when the compiler knows the types at compile time.
~/dev cat hack_vtable.cc
// change vtable of existing object to intercept virtual dispatch...
#include <iostream>
struct B
{
virtual void f() { std::cout << "B::f()\n"; }
std::string s_;
};
struct D : B
{
virtual void f() { std::cout << "D::f()\n"; }
};
struct E
{
virtual void f() { std::cout << "E::f()\n"; }
};
int main()
{
B* p = new B();
p->s_ = "hello";
new (p) D(); // WARNING: reconstructs B members
p->f();
std::cout << '\'' << p->s_ << "'\n"; // no longer "hello"
p->s_ = "world";
new (p) E();
p->f(); // correctly calls E::f()
std::cout << '\'' << p->s_ << "'\n"; // still "world"
}
~/dev try hack_vtable
make: `hack_vtable' is up to date.
D::f()
''
E::f()
'world'
Well, even if you're casting your Base object as a Derived one, internally, it's still a Base object: the vftable of your object (the actual map of functions to RAM pointers) is not updated.
I don't think there is any way to do what you want to do and I don't understand why you'd like to do it.
In this question downcast problem in c++ Robs answer should also be the answer to your problem.
Not at least in legal way. To call Derived class function, you need to have Derived object being referred.

Pointers to virtual member functions. How does it work?

Consider the following C++ code:
class A
{
public:
virtual void f()=0;
};
int main()
{
void (A::*f)()=&A::f;
}
If I'd have to guess, I'd say that &A::f in this context would mean "the address of A's implementation of f()", since there is no explicit seperation between pointers to regular member functions and virtual member functions. And since A doesn't implement f(), that would be a compile error. However, it isn't.
And not only that. The following code:
void (A::*f)()=&A::f;
A *a=new B; // B is a subclass of A, which implements f()
(a->*f)();
will actually call B::f.
How does it happen?
It works because the Standard says that's how it should happen. I did some tests with GCC, and it turns out for virtual functions, GCC stores the virtual table offset of the function in question, in bytes.
struct A { virtual void f() { } virtual void g() { } };
int main() {
union insp {
void (A::*pf)();
ptrdiff_t pd[2];
};
insp p[] = { { &A::f }, { &A::g } };
std::cout << p[0].pd[0] << " "
<< p[1].pd[0] << std::endl;
}
That program outputs 1 5 - the byte offsets of the virtual table entries of those two functions. It follows the Itanium C++ ABI, which specifies that.
Here is way too much information about member function pointers. There's some stuff about virtual functions under "The Well-Behaved Compilers", although IIRC when I read the article I was skimming that part, since the article is actually about implementing delegates in C++.
http://www.codeproject.com/KB/cpp/FastDelegate.aspx
The short answer is that it depends on the compiler, but one possibility is that the member function pointer is implemented as a struct containing a pointer to a "thunk" function which makes the virtual call.
I'm not entirely certain, but I think it's just regular polymorphic behavior. I think that &A::f actually means the address of the function pointer in the class's vtable, and that's why you aren't getting a compiler error. The space in the vtable is still allocated, and that is the location you are actually getting back.
This makes sense because derived classes essentially overwrite these values with pointers to their functions. This is why (a->*f)() works in your second example - f is referencing the vtable that is implemented in the derived class.