C++ calling function results in calling another function - c++

I`ve faced with a very interesting issue, i hope you can help me what i am doing wrong here..
class abstract1
{
public:
virtual ~ abstract1(){};
virtual void funk1()=0;
virtual void punk1()=0;
};
class abstract2
{
public:
virtual ~ abstract2(){};
virtual void funk2()=0;
virtual void punk2()=0;
};
class Derived: public abstract1,
public abstract2
{
public:
Derived(){ cout<<"Derived constructor"<<endl;};
~Derived() {cout <<"Derived destructor" <<endl;};
void funk1(){
cout<<"funk1 function in Derived!!!"<<endl;
};
void punk1(){
cout<<"punk1 in Derived!!!"<<endl;
};
void funk2(){
cout<<"funk2 function in Derived!!!"<<endl;
};
void punk2(){
cout<<"punk2 in Derived!!!"<<endl;
};
};
class myapi{
public:
void start(void *_drved){
drved=(abstract2*)_drved;
};
void callback(){
drved->funk2();
drved->punk2();
}
protected:
abstract2* drs;
};
Here I have defined two base classes and one derived class inheriting from these two. main() implementation is as follows:
int main() {
Derived* myderived =new Derived();
myapi* dbmodule= new myapi();
dbmodule->start(myderived);
dbmodule->callback();
return 0
}
I expect to see that funk2 and punk2 are getting called one after another. However result is shockingly new to me . Callback() seems to call funk1 and punk1. Screen output is like below:
Derived constructor
funk1 function in Derived!!!
punk1 in Derived!!!
Hope you can let me know what i am getting wrong here.Thanks

The answers and comments do not quite go down to the bottom of it, so I will try to address this.
On the first look, using void* casts as shown should not be of a problem, because you end up casting to the base, right? So even if at some point the information of the type was lost through void*, it should be re-aquired? The virtual function calls should still work?
They would, if not for multiple inheritance. In single-inheritance scenario, correct virtual functions would be still called. But when you have multiple inheritance, you need to know the type to properly calculate offset to one of the bases.
A bit of background. Virtual functions are usually represented through so-called VTABLE - which can be thought of as a table of pointers to functions. For every specific class there is a copy of such table (per class, not per object!) which will have pointers set to corresponding member functions, defined in that class. Every object of the class has a pointer to this table (so that multiple objects of the same class all share the same table).
For single inheritance, there is only one vtable pointer and it's the first member of the class. As a result, it doesn't matter how you cast your pointer in between, as long as you cast it to correct type before calling virtual function, you will be calling the proper virtual function.
However, in case of multiple non-virtual inheritance, there is more than one ponter to vtable. You have a pointer for every parent! So when you cast to the parent, the resulting pointer would point to one of the bases - by offsetting the pointer to the object to the pointer to vtable of the class you cast to. If you first cast to void*, this crucial step is not performed, and resulting void* is simply pointing to the first vtable in your class. And even when you cast back to the proper base, there is no longer needed information to perform proper offsetting - all the compiler sees is the void*, it would have no ither information - and the pointer remains pointing to the first vtable.
As a result of all this, you end up calling virtual functions from incorrect base!

Related

Why does a base pointer can access derived member variable in virtual funtion

class Base {
public:
virtual void test() {};
virtual int get() {return 123;}
private:
int bob = 0;
};
class Derived: public Base{
public:
virtual void test() { alex++; }
virtual int get() { return alex;}
private:
int alex = 0;
};
Base* b = new Derived();
b->test();
When test and get are called, the implicit this pointer is passed in. Is it because Derived classes having a sub memory layout that is identical to what a pure base object would be, then this pointer works for both as a base pointer and derived pointer?
Another way to put it is, the memory layout for Derived is like
vptr <-- this
bob
alex
That is why it can use alex in b->test(), right?
Inside of Derived's methods, the implicit this pointer is always a Derived* pointer (more generically, the this pointer always matches the class type being called). That is why Derived::test() and Derived::get() can access the Derived::alex member. That has nothing to do with Base.
The memory layout of a Derived object begins with the data members of Base, followed by optional padding, followed by the data members of Derived. That allows you to use a Derived object wherever a Base object is expected. When you pass a Derived* pointer to a Base* pointer, or a Derived& reference to a Base& reference, the compiler will adjust the pointer/reference accordingly at compile-time to point at the Base portion of the Derived object.
When you call b->test() at runtime, where b is a Base* pointer, the compiler knows test() is virtual and will generate code that accesses the appropriate slot in b's vtable and call the method being pointed at. But, the compiler doesn't know what derived object type b is actually pointing at in runtime (that is the whole magic of polymorphism), so it can't automatically adjust the implicit this pointer to the correct derived pointer type at compile-time.
In the case where b is pointing at a Derived object, b's vtable is pointing at Derived's vtable. The compiler knows the exact offset of the start of Derived from the start of Base. So, the slot for test() in Derived's vtable will point to a private stub generated by the compiler to adjust the implicit Base *this pointer into a Derived *this pointer before then jumping into the actual implementation code for Derived::test().
Behind the scenes, it is roughly (not exactly) implemented like the following pseudo-code:
void Derived_test_stub(Base *this)
{
Derived *adjusted_this = reinterpret_cast<Derived*>(reinterpret_cast<uintptr_t>(this) + offset_from_Base_to_Derived);
Derived::test(adjusted_this);
}
int Derived_get_stub(Base *this)
{
Derived *adjusted_this = reinterpret_cast<Derived*>(reinterpret_cast<uintptr_t>(this) + offset_from_Base_to_Derived);
return Derived::get(adjusted_this);
}
struct vtable_Base
{
void* funcs[2] = {&Base::test, &Base::get};
};
struct vtable_Derived
{
void* funcs[2] = {&Derived_test_stub, &Derived_get_stub};
};
Base::Base()
{
this->vtable = &vtable_Base;
bob = 0;
}
Derived::Derived() : Base()
{
Base::vtable = &vtable_Derived;
this->vtable = &vtable_Derived;
alex = 0;
}
...
Base *b = new Derived;
//b->test(); // calls Derived::test()...
typedef void (*test_type)(Base*);
static_cast<test_type>(b->vtable[0])(b); // calls Derived_test_stub()...
//int i = b->get(); // calls Derived::get()...
typedef int (*get_type)(Base*);
int i = static_cast<get_type>(b->vtable[1])(b); // calls Derived_get_stub()...
The actual details are a bit more involved, but that should give you a basic idea of how polymorphism is able to dispatch virtual methods at runtime.
What you've shown is reasonably accurate, at least for a typical implementation. It's not guaranteed to be precisely as you've shown it (e.g., the compiler might easily insert some padding between bob and alex, but either way it "knows" that alex is at some predefined offset from this, so it can take a pointer to Base, calculate the correct offset from it, and use what's there.
Not what you asked about, so I won't try to get into detail, but just a fair warning: computing such offsets can/does get a bit more complex when/if multiple inheritance gets involved. Not so much for accessing a member of the most derived class, but if you access a member of a base class, it has to basically compute an offset to the beginning of that base class, then add an offset to get to the correct offset within that base class.
A derived class is not a seperate class but an extension. If something is allocated as derived then a pointer (which is just an address in memory) will be able to find everything from the derived class. Classes don't exist in assembly, the compiler keeps track of everything according to how it is allocated in memory and provides appropriate checking accordingly.

When is the virtual function table set to 0

I'm analyzing an access violation in our application that occurs because it tries to call a virtual function on an object whose virtual function table points to 0. So I'd like to know at what points in an object's lifetime is the virtual function table pointer not set or explicitly set to zero?
(We use Visual C++ 10 as a compiler.)
The vtable pointer will never be 0 while the object is in a valid state. During construction and destruction, while the object has a dynamic type of an abstract base class, the vtable will point to the abstract base class vtable, which will include pure virtual functions, but the vtable pointer itself will still be non-zero.
The only time the vtable pointer can be zero is before construction or after destruction.
If the vtable pointer is truly zero, then you may have used a VC++ extension such as:
class __declspec(novtable) Base {
public:
Base();
virtual void proc();
};
Here __declspec(novtable) tells the compiler the class doesn't need a vtable, because no virtual functions will be called on it until a derived class has installed its own vtable. If you then call Base::proc() before that has happened, you may get the error.
More likely the vtable itself is non-zero, but function's slot in it is zero, due to the function being pure virtual:
class Base {
public:
virtual void proc() = 0;
};
and then someone called it anyway with code like:
void Derived::proc() {
Base::proc();
// Derived-specific stuff here.
};
This can happen because the author of Derived assumed their override needed to call the Base version, even though the Base version doesn't exist.
Either way, one approach to finding this would be to stop all the base class shenanigans, define the function normally, and see what calls it. Eg:
class Base {
public:
virtual void proc() {
assert( typeof(*this) != typeof(Base) ); // Break-point here.
}
};

Why is a virtual table required only in case of virtual functions?

From http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/, code such as
class Base
{
public:
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
generates a virtual table similar to http://www.learncpp.com/images/CppTutorial/Section12/VTable.gif:
The virtual table as above makes sense. After all the objects need a way to call functions, and need to use function pointers to find them.
What I do not understand is why this is only required in case of using virtual functions? I am definitely missing something since a virtual table does not directly depend on virtual functions.
As an example, if the code being used were
class Base
{
public:
void function1() {};
void function2() {};
};
...
Base b;
b.function1();
and there is no virtual table (meaning there is no pointer to where the function resides), how would the b.function1() call resolve?
Or is it that we have a table in this case as well, just that it is not called a virtual table? In that case the question would arise as to why we need a new kind of table for virtual functions?
[If] there is no virtual table (meaning there is no pointer to where the function resides), how would the b.function1() call resolve?
There is a "pointer", inside the compiler as it's parsing and analysing your code. The compiler's the thing that decides where the function will be generated, so it knows how calls to said function should resolve. In concert with the linker, this all happens tidily within the build process.
The only reason that this doesn't work for virtual functions is that which function you call depends on a type known only at runtime; in fact the same function pointers are present verbatim in the virtual table, written there by the compiler. It's just that in this case, there are multiple to choose from, and they cannot be chosen from until long (read: potentially months or even years!) after the compiler ceases to be involved at all.
There's already a good answer, but I'll attempt a slightly simpler (albeit longer) one:
Think of a non-virtual method of the form
class A
{
public:
int fn(int arg1);
};
as equivalent to a free function of the form:
int fn(A* me, int arg1); // overload A
where me corresponds to the this pointer inside the method version.
If you now have a subclass:
class B : public A
{
public:
int fn(int arg1);
};
this is equivalent to a free function like this:
int fn(B* me, int arg1); // overload B
Note that the first argument has a different type to the free function we declared earlier - the function is overloaded on the type of the first argument.
If you now have some code calling fn() it will choose the overload based on the static type (compile time type) of the first argument:
A* p;
B* q;
// ...
// assign valid pointer values to p and q
// ...
int a = fn(p, 0); // will call overload A
int b = fn(q, 0); // will call overload B
The compiler can and will determine the function to call at compile time in each case and can emit assembly code with a fixed function address or address offset. The concept of a runtime virtual table is nonsensical here.
Now, when I said to think of the method version as equivalent to the free function version, you'll find that at the assembly language level, they are equivalent. The only difference will be the so-called mangled name that encodes the type in the compiled function name and distinguishes overloaded functions. The fact that you call methods via p->fn(0), that is, with the first argument before the method name is pure syntactic sugar - you're not actually dereferencing the pointer p in the example, even though it looks like it. You're just passing p as the implicit this argument. So, to continue the above example,
p->fn(0); // will always call A::fn()
q->fn(0); // will always call B::fn()
because fn being a non-virtual method means the compiler dispatches on the this pointer's static type, which it can do at compile time.
Although virtual functions use the same calling syntax as non-virtual member functions, you are in fact dereferencing the object pointer; specifically, you're dereferencing the pointer to the object's class's virtual table.

Low level details of inheritance and polymorphism

This question is one of the big doubts that looms around my head and is also hard to describe it in terms of words . Some times it seems obvious and sometimes a tough one to crack.So the question goes like this::
class Base{
public:
int a_number;
Base(){}
virtual void function1() {}
virtual void function2() {}
void function3() {}
};
class Derived:public Base{
public:
Derived():Base() {}
void function1() {cout &lt&lt "Derived from Base" &lt&lt endl;
virtual void function4() {cout &lt&lt "Only in derived" &lt&lt endl;}
};
int main(){
Derived *der_ptr = new Derived();
Base *b_ptr = der_ptr; // As just address is being passed , b_ptr points to derived object
b_ptr -> function4(); // Will Give Compilation ERROR!!
b_ptr -> function1(); // Calls the Derived class overridden method
return 0;
}
Q1. Though b_ptr is pointing to Derived object, to which VTABLE it accesses and HOW ? as b_ptr -> function4() gives compilation error. Or is it that b_ptr can access only upto that size of Base class VTABLE in Derived VTABLE?
Q2. Since the memory layout of the Derived must be (Base,Derived) , is the VTABLE of the Base class also included in the memory layout of the Derived class?
Q3. Since the function1 and function2 of base class Vtable points to the Base class implementation and function2 of Derived class points to function2 of Base class, Is there really a need of VTABLE in the Base class?? (This might be the dumbest question I can ever ask, but still I am in doubt about this in my present state and the answer must be related to answer of Q1 :) )
Please Comment.
Thanks for the patience.
As a further illustration, here is a C version of your C++ program, showing vtables and all.
#include <stdlib.h>
#include <stdio.h>
typedef struct Base Base;
struct Base_vtable_layout{
void (*function1)(Base*);
void (*function2)(Base*);
};
struct Base{
struct Base_vtable_layout* vtable_ptr;
int a_number;
};
void Base_function1(Base* this){}
void Base_function2(Base* this){}
void Base_function3(Base* this){}
struct Base_vtable_layout Base_vtable = {
&Base_function1,
&Base_function2
};
void Base_Base(Base* this){
this->vtable_ptr = &Base_vtable;
};
Base* new_Base(){
Base *res = (Base*)malloc(sizeof(Base));
Base_Base(res);
return res;
}
typedef struct Derived Derived;
struct Derived_vtable_layout{
struct Base_vtable_layout base;
void (*function4)(Derived*);
};
struct Derived{
struct Base base;
};
void Derived_function1(Base* _this){
Derived *this = (Derived*)_this;
printf("Derived from Base\n");
}
void Derived_function4(Derived* this){
printf("Only in derived\n");
}
struct Derived_vtable_layout Derived_vtable =
{
{ &Derived_function1,
&Base_function2},
&Derived_function4
};
void Derived_Derived(Derived* this)
{
Base_Base((Base*)this);
this->base.vtable_ptr = (struct Base_vtable_layout*)&Derived_vtable;
}
Derived* new_Derived(){
Derived *res = (Derived*)malloc(sizeof(Derived));
Derived_Derived(res);
return res;
}
int main(){
Derived *der_ptr = new_Derived();
Base *b_ptr = &der_ptr->base;
/* b_ptr->vtable_ptr->function4(b_ptr); Will Give Compilation ERROR!! */
b_ptr->vtable_ptr->function1(b_ptr);
return 0;
}
Q1 - name resolution is static. Since b_ptr is of type Base*, the compiler can't see any of the names unique to Derived in order to access their entries in the v_table.
Q2 - Maybe, maybe not. You have to remember that the vtable itself is simply a very common method of implementing runtime polymorphism and is actually not part of the standard anywhere. No definitive statement can be made about where it resides. The vtable could actually be some static table somewhere in the program that is pointed to from within the object description of instances.
Q3 - If there's a virtual entry in one place there must be in all places otherwise a bunch of difficult/impossible checks would be necessary to provide override capability. If the compiler KNOWS that you have a Base and are calling an overridden function though, it is not required to access the vtable but could simply use the function directly; it can even inline it if it wants.
A1. The vtable pointer is pointing to a Derived vtable, but the compiler doesn't know that. You told it to treat it as a Base pointer, so it can only call methods that are valid for the Base class, no matter what the pointer points to.
A2. The vtable layout is not specified by the standard, it isn't even officially part of the class. It's just the 99.99% most common implementation method. The vtable isn't part of the object layout, but there's a pointer to the vtable that's a hidden member of the object. It will always be in the same relative location in the object so that the compiler can always generate code to access it, no matter which class pointer it has. Things get more complicated with multiple inheritance, but lets not go there yet.
A3. Vtables exist once per class, not once per object. The compiler needs to generate one even if it never gets used, because it doesn't know that ahead of time.
b_ptr points to the Derived vtable- but the compiler can't guarantee that the derived class has a function_4 in it, as that's not contained within the base vtable, so the compiler doesn't know how to make the call and throws an error.
No, the vtable is a static constant somewhere else in the program. The base class merely holds a pointer to it. A Derived class may hold two vtable pointers, but it might not.
In the context of these two classes, then Base needs a vtable to find Derived's function1, which actually is virtual even though you didn't mark it as so, because it overrode a base class virtual function. However, even if this wasn't the case, I'm pretty sure that the compiler is required to produce the vtables anyway, as it has no idea what other classes you have in other translation units that may or may not inherit from these classes and override their virtual functions in unknowable ways.
First, and most important, remember that C++ doesn't do a lot of run-time introspection of any kind. Basically, it needs to know everything about the objects at compile time.
Q1 - b_ptr is a pointer to a Base. Therefore it can only access things that are present in a Base object. No exceptions. Now, the actual implementation may change depending on the actual type of the object, but there's no getting around the method having to be defined in Base if you want to call it through a Base pointer.
Q2 - The simple answer is 'yes, the vtable for a base has to be present in a derived', but there are a LOT of possible strategies for how to layout a vtable, so don't get hung up on it's exact structure.
Q3 - Yes, there must be a vtable in the Base class. Everything that calls virtual functions in a class will go through the vtable so that if the underlying object is actually a Derived, everything can work.
Now that's not an absolute, because if the compiler can be ABSOLUTELY sure that it knows what it's got (as might be the case of a Base object that's declared on the local stack), then the compiler is allowed to optimize out the vtable lookups, and might even be allowed to inline the function.
All of this depends on the implementation. But here are the answers for the usual simplest way using "vtables".
The Base class has a vtable pointer, so the underlying representation is something like this pseudo-code:
struct Base {
void** __vtable;
int a_number;
};
void* __Base_vtable[] = { &Base::function1, &Base::function2 };
void __Base_ctor( struct Base* this_ptr ) { this_ptr->__vtable = __Base_vtable; }
The Derived class includes a Base class subobject. Since that has a place for a vtable, Derived doesn't need to add another one.
struct Derived {
struct Base __base;
};
void* __Derived_vtable[] =
{ &Derived::function1, &Base::function2, &Derived::function4 };
void __Derived_ctor( struct Derived* this_ptr ) {
__Base_ctor( &this_ptr->__base );
this_ptr->__base.__vtable = __Derived_vtable;
}
The "vtable for the Base class", __Base_vtable in my pseudocode, is needed in case somebody tries new Base(); or Base obj;.
All of the above gets more complicated when multiple inheritance or virtual inheritance is involved....
For the line b_ptr -> function4();, this is a compile-time error, not much related to vtables. When you cast to a Base* pointer, you may only use that pointer in the ways defined by class Base (because the compiler doesn't "know" any more whether it's really a Derived, a Base, or some other class). If Derived has a data member of its own, you can't access it through that pointer. If Derived has a member function of its own, virtual or not, you can't access it through that pointer.

Which function to call? (delegate to a sister class)

I just read about this in the C++ FAQ Lite
[25.10] What does it mean to "delegate to a sister class" via virtual inheritance?
class Base {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
class Der1 : public virtual Base {
public:
virtual void foo();
};
void Der1::foo()
{ bar(); }
class Der2 : public virtual Base {
public:
virtual void bar();
};
class Join : public Der1, public Der2 {
public:
...
};
int main()
{
Join* p1 = new Join();
Der1* p2 = p1;
Base* p3 = p1;
p1->foo();
p2->foo();
p3->foo();
}
"Believe it or not, when Der1::foo() calls this->bar(), it ends up calling Der2::bar(). Yes, that's right: a class that Der1 knows nothing about will supply the override of a virtual function invoked by Der1::foo(). This "cross delegation" can be a powerful technique for customizing the behavior of polymorphic classes. "
My question is:
What is happening behind the scene.
If I add a Der3 (virtual inherited from Base), what will happen? (I dont have a compiler here, couldn't test it right now.)
What is happening behind the scene.
The simple explanation is that, because inheritance from Base is virtual in both Der1 and Der2, there is a single instance of the object in the most derived object Join. At compile time, and assuming (which is the common case) virtual tables as dispatch mechanism, when compiling Der1::foo it will redirect the call to bar() through the vtable.
Now the question is how the compiler generates vtables for each of the objects, the vtable for Base will contain two null pointers, the vtable for Der1 will contain Der1::foo and a null pointer and the vtable for Der2 will contain a null pointer and Der2::bar [*]
Now, because of virtual inheritance in the previous level, when the compiler processes Join it will create a single Base object, and thus a single vtable for the Base subojbect of Join. It effectively merges the vtables of Der1 and Der2 and produces a vtable that contains pointers to Der1::foo and Der2::bar.
So the code in Der1::foo will dispatch through Join's vtable to the final overrider, which in this case is in a different branch of the virtual inheritance hierarchy.
If you add a Der3 class, and that class defines either of the virtual functions, the compiler will not be able to cleanly merge the three vtables and will complain, with some error relating to the ambiguity of the multiply defined method (none of the overriders can be considered to be the final overrider). If you add the same method to Join, then the ambiguity will no longer be a problem, as the final overrider will be the member function defined in Join, so the compiler is able to generate the virtual table.
[*] Most compilers will not write null pointers here, but rather a pointer to a generic function that will print an error message and terminate the application, allowing for better diagnostics than a plain segmentation fault.
If you add a Der3 what will happen depends on which class it inherits from.
As you know, instantiating a class is only possible when all virtual functions have been defined; otherwise you can only make pointers to them. This is to prevent constructing partially defined objects.
In your example you cannot instantiate Der1 nor Der2 directly because in Der1, bar() is still pure virtual and in Der2, foo() is pure virtual.
Your Join class can be instantiated because it inherits from both and has therefore no pure virtual function.
Once you have made an instance of a class, you can instantiate pointers to non-instantiable classes by dynamic_casting.
From the moment a class has been instantiated, the virtual function mechanism, that works with a table of pointer to functions, will still call the functions that have been defined at instantiation time.
So the key here is that when you create your object, you create an instance of Join. Its virtual functions are defined because you are able to create the object. From that moment, you can call the virtual functions with any pointer to a base class.
I see why this is interesting to explore. In real code this would probably be hardly useful however. As others pointed out, virtual inheritance is more of a fix-this-bad-design-to-work-somehow tool, than a valid desing tool.
Your code produces warnings in VS2010 - the compiler is making you know that dominance is being used. Of course thats not a show stopper, but another discouragement to use this.
If you introduce Der3 like this
class Der3 : public virtual Base {
public:
void bar() {}
};
class Join : public Der1, public Der2, public Der3 {}
the code fails to compile because of ambiguous inheritance of 'void Base::bar(void)'
One point is missing in the discussion ( none-the-less this is quite informative and thanks to all ).
When you 'virtually inherit' a class. What happens is: a pointer to the virtual base class is kept by most of the compilers ( it can be implemented in different ways by different compilers). So if you take the size of Der1 and Der2, it would be atleast 4 bytes on 32 bit and 8 bytes on 64 bit. Because they have a pointer to the virtual base class and therefore, no ambiguity. That is why when you create the object of Join, it first calls the constructor of Virtual Base class ( not really the first call, but it initializes the pointer which came to it through Der1 and Der2 first in its construtor ). In Join compiler can check the pointer name / type and then it makes sure that only one pointer of virtual base class comes to it from Der1 and Der2. You can check even this by sizeof operator. As we know that compiler puts the calls in the constructor silently. Therefore, it first calls the Virtual Base class's constructor in Depth First way. ( can be checked using all the base classes as virtual derivation ). Rest is already explained
This is a pretty stupid example imo and a perfect example of academics making themselves look clever. If this situation ever came up, it would almost CERTAINLY be because of a bug, specifically forgetting to make Der1::foo() virtual.
Edit:
I misread the class definitions. Which is exactly the problem with this type of design. It takes a lot of thought to determine exactly what would happen in each of these cases, which is bad. Making your code readable is by far better than being "clever" like this.