virtual derived class of a non-virtual base class - c++

I have a virtual class that has been derived from a non virtual class. But when I c-style cast the derived class to base class, the class is corrupted. I am looking at the member variables using the debugger and the member variables are all corrupted when I do that cast. I see there is a 4 byte discrepency when I do that cast(may be the virtual pointer) using debugger.
For Ex:
class A//non-virtual class
{
~A();
int fd;
};
class B:public A
{
virtual ~B();
};
Now say the address of obj of type B is: 0x9354ed0.
Now when I cast it (A*)(0x9354ed0) debugger moves the bytes by 4 bytes. So starting address of the casted obj is 0x935ed4
Is it wrong to cast a derived virtual class to base non-virtual class? What is the reason for 4 byte discrepancy?
And what is the right way to cast it? Thanks for any input or explanation.

Here is what you described.
class A
{
public:
~A();
// other stuff
};
class B: public A
{
public:
virtual ~B();
// other stuff
};
It is perfectly legal to derive a class from a non-virtual base class, and to make the derived class virtual. The 4 bytes offset (can be 8) corresponds to a hidden member variable of type pointer that points to the virtual functions table of the class.

When you cast pointers across the hierarchy, actual numerical pointer values might change. There's nothing wrong with the fact that it changes. There's noting wrong with such a cast. How the numerical pointer values change depend on the physical layout of the class. It is an implementation detail.
In your example, the 4 byte change in pointer value might easily be caused by the presence of virtual table pointer in the derived class.
The change in pointer value will not corrupt any member variables. The example in your original post does not show any "corrupted member variables" and in general your claim about some member variables getting "corrupted" doesn't make much sense. Please, when you make such claims, illustrate them with an example, so that people can understand what on Earth your are talking about.
Update:
The fact that base class subobjects might have non-zero offsets inside the derived classes immediately mean that in order to perform a proper cast from derived pointer type to base pointer type the compiler must know the source type and the destination type and the relationship between them. For example, if you do this
B* pb = /* whatever */;
A* pa = pb;
the compiler will know how to properly offset pointer pa from pointer pb. But of you do this
A* pa = (void *) pb;
the compiler will forget about the relationship between A and B, fail to perform the proper offset and produce the invalid value of pa. The effect would be the same as in
A* pa = reinterpret_cast<A*>(pb);
If you do it this way, the result will be meaningless. So, just don't do it.
Of course, if you manually inspect the numerical value of pb and find out that it is, say, 0x12345678, and then do
A* pa = (A*) 0x12345678;
you will also get completely meaningless results, because the computer has no way to know that it has to perform the proper offset of the pointer.
This will produce an illusion of members of A getting "corrupted", while in fact the only thing that is corrupted is your pointer. And you are the one who corrupted it.

If that is the shell of the code you are using then you aren't deriving the class B from class A. If you wanted to do that you would need to do this:
class A
{
public:
virtual ~A();
// other stuff
};
class B: public A
{
public:
virtual ~B();
// other stuff
};
I really don't think you can cast the way that you were hoping to in your question. If you are using virtual functions and derived classes then they need to be declared virtual upon first usage. Plus, I'm not 100% sure but if you have any virtual destructors you need to have all virtual destructors in your heirarchy.
Hope that helps,
nmr

The missing four bytes are, indeed, the vptr of the object; since class A has no vtable, a pointer to A has no vptr.
While it is actually legal deriving a class with virtual methods from another class with none, it is not a good idea. Inheriting from a class with no virtual methods is usually unsound, since that class is not intended to be used polymorphically, which is the main reason behind inheritance. All kinds of bad things can happen if you do it. If you try to use derived class objects through base class pointers, you may well run into the dreaded undefined behaviour (most likely a crash). For instance, trying to delete a base class pointer pointing to a derived class object.

Its legal to point derived class object using base class pointer
that's called run time polymorphism i.e. based on dynamic type of object functions are dispatched.
When you define a class with virtual function,a table comprising of virtual function address is formed called virtual function table.
When you declare an object of a class with virtual function , a virtual pointer pointing to corresponding virtual function table is insert into it.

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.

Can I delete a union component without checking whether it stores that object?

I mean the following. I have a few classes which inherit the same base class. Union consists of pointers of these classes:
#include "stdio.h"
class A {
public:
A() { printf("A\n"); }
virtual ~A() { printf("~A\n"); }
};
class B : public A {
public:
B() { printf("B\n"); }
virtual ~B() { printf("~B\n"); }
};
class C : public A {
public:
C() { printf("C\n"); }
virtual ~C() { printf("~C\n"); }
};
int main() {
union {
B* b;
C* c;
} choice;
choice.b = new B();
delete choice.c; //We have B object, but deleting C
return 0;
}
It seems to work, but I'm not sure if it isn't implementation-specific behaviour. Can I use such weird deleting method or should I remember a type of stored object and delete it respectively?
P.S. I use C++11 and want it works on both GCC and Visual C++ (2012 and higher). In a real project I have more complex class hierarchy but all of them are successors (directly or indirectly) of the same abstract base class
This is a double dose of undefined behavior. First, you can't delete a B through a pointer to C. ยง5.3.5 [expr.delete]/p3:
In the first alternative (delete object), if the static type of the
object to be deleted is different from its dynamic type, the static
type shall be a base class of the dynamic type of the object to be
deleted and the static type shall have a virtual destructor or the
behavior is undefined. In the second alternative (delete array) if the
dynamic type of the object to be deleted differs from its static type,
the behavior is undefined.
Second, accessing the inactive member of a union is also undefined behavior in C++.
There's no need to use an union here anyway. B and C share the same base class, so you can just store the pointer in an A *.
You shouldn't. You are only allowed to read from the union member you last wrote into and you're only allowed to delete an object through a pointer to a base class (if it has a virtual destructor). It may seem to work now, but you may find it to break randomly in the future, usually due to an aggressive optimizer.
Why don't you store a pointer to A instead of the union?
As it has been said in other answer, this is not proper C++.
My impression is that you want to keep an union of pointers because in certain circumstances you need an instance of a (sub)class of B, and in another an instance of C, with the issue of B and C having not quite the same interface. Perhaps you store several of these in a container, or simply you don't know until runtime which instance will be used.
So you may keep your code as it was, with perhaps a type tag somewhere indicating which instance has been created, and then use a switch each time you need to determine the correct code to run, or you could leverage your classes to actually invoke the proper function at run time, by including in the common base class of B and C(1) a virtual method, and overload this method in B and C with the proper branch of the switch, then replace the union with a simple pointer to the base class.
(1) that base class doesn't have to be A: if you don't want to clutter your class tree, just make a different class having the minimal interface needed there, and thanks to C++ multiple inheritance, have B and C inherit from it as well. Don't forget the virtual destructor!
For me this case looks legit and there is no undefined behaviour.
He is using type-punning and it is legit because it B* b and C* c in union members is a pointers and could be converted to char array.
Both B and C have virtual destructor because of base class (not because base is a same! but because base have virtual destructor).
12.4.9 If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.
While destructor call, (because it is virtual) exact function address will be picked up from choice variable and proper destructor sequence will be called. So there is no ANY undefined behaviour at all.

query on runtime polymorphism in C++

class base
{
public:
virtual void showbase() {
// ----------
}
};
class base1 {
public:
virtual void showbase1() {
// -------
}
};
class derived : public base, public base1
{
void showbase() {
// ----
}
void showbase1() {
// -------
}
};
int main()
{
base* p = new derived();
p->showbase1();
base1* p1 = new derived();
p1->showbase();
}
As per my understanding about virtual function is that compiler deals it with run time (vtable mechanism), then why I am getting compile time error.
To simulate a compiler, consider what a compiler sees:
class base
{
public:
virtual void showbase() {
// ----------
}
};
base* p = /*blah blah*/;
p->showbase1();
Yes, base is a polymorphic class. And p is indeed a pointer-tobase. But since p points just to a base, and importantly not to a base1 (where showbase1 lives) the compiler interprets the above code like this. Obviously, I'm paraphrasing:
Here is a class named `base` with a single virtual method called `showbase`.
Here is a pointer to a `base` object. Call the method named `showbase1`
And the compiler complains:
Um, excuse me buddy, but base doesn't have a method called
showbase1.
You asked:
[My] understanding about virtual function is that compiler deals with
it at run time. Why I am getting compile time error?
Because the code you've written is nonsense. Here basically is how polymorphism works.
You define a base class with virtual methods.
You define a derived class that overrides those virtual methods.
The compiler creates a vtable which maps the names of the methods in the base class to the implementation in the derived class.
When you call a method in the base class through a pointer (or ref) to the base class, the derived class' implementation is called.
But what you are trying to do is:
Define a base class with virtual methods.
Define a derived class which overrides those virtual methods.
Call a function in a completely different class.
As per my understanding about virtual function is that compiler deals it with run time (vtable mechanism), then why I am getting compile time error.
"Deals with it" is pretty vague and vtables are not magic; In C++ virtual dispatch allows for the actual function called to be one that overrides the statically declared virtual function. That means that the function which is being overridden must be known at compile time.
The vtable does not contain information that would be necessary to look up functions at run-time. Instead, it's basically just a list of pointers to overriding functions. The base provides a complete list of its virtual functions and so, given a particular base type, the compiler knows at compile-time where to go in the vtable for that base for a particular function override; The compiler can generate code that goes directly to that spot in the vtable, gets the pointer, and calls the overriding function.
Then, at run-time, when the actual object of derived type is created, the derived object's constructor fills in the base's vtable, so that anything checking the vtable will get pointers to the derived type's functions.
So the problem with your code is that the function you're calling, showbase(), is not on the list of virtual functions for the type the compiler knows you're accessing, base1; The compiler can't know where in base1's vtable to get a pointer for a function override named showbase(), because there is no such entry in base1's vtable.
A base class pointer to a derived class can only access the member functions defined in the base class. It is illegal to try and access other functions defined in the derived class through it. In your case base class does not define showbase1 and therefore this is illegal
base* p = new derived();
p->showbase1(); //illegal
However, you can do this:
p->showbase(); // legal because showbase is a member function of base
Similarly you can't access showbase1 using a base class pointer
base1* p1 = new derived();
p1->showbase(); //illegal
p1->showbase1(); //legal
Your base class(es) only know about their own member functions, so you can't use it this way. You could do this instead:
base* p = new derived();
p->showbase();
base1* p1 = new derived();
p1->showbase1();
To answer your question about runtime polymorphism, it is dealing with runtime polymorphism (late binding) via the vtable, as you say. But with multiple inheritance, there is essentially a vtable for for each base class. You can't access one base class' vtable via a pointer to the other base class.
p'static type s type is base and hence you can only call with it functions that have been definied into base even if at the end, it will be the functions from derived which will be called because p's dynamic type is derived
Same thing happens for p1.
Maybe you meant p->showbase(); and p1->showbase1();

Get address of base object from derived object

I'm getting a very confusing error in my program. I think I may have two different objects of the same class where I thought I had the same object. It is confusing because I am dealing with a very large framework where it is not simple to obtain a pointer to the object I need.
My question is, if I have a class Derived which in inherits from Base, and I have a pointer to a Derived object, how can I get the address of the Base object from the derived object? I am working with the source code of the Base Class and am printing out the address of "this" in Base. In another part of my code a retrieve a pointer to a Derived. I need to be able to print the address of the Base object via my Derived object to determine whether I have a pointer to the particular Derived object I need.
I may have a great misunderstanding of how the addresses work in C++ in inheritance. Perhaps their is only one object, not a base object linked to a derived object?
Thank you very much
Edit:
The reason I want to do this is purely for debugging. The problem is that the code base I'm using does not contain many interfaces or protected members, so I am having to edit the source code to access a certain piece of information. However, my program crashes when I call a method I added to the Base class using a specific Derived pointer. I need to be able to print the address of the base object in this case so that I can determine whether this is the correct object or whether I am getting this error because I actually have a pointer to the wrong object. I realize I can add code to the derived class to cause it to print its address, but I was just wondering if it was possible to get the address without editing the source code any more. Thanks
Going from a pointer to derived class to a pointer to a base class is easy:
Derived * derived_ptr = < some pointer >;
Base * base_ptr = derived_ptr;
If you want to be pedantic, you can use static_cast on the right hand side of the assignment:
Base * base_ptr = static_cast<Base*>(derived_ptr);
Going from a pointer to a base class to a pointer to a derived class uses dynamic_cast:
Derived * derived_ptr = dynamic_cast<Derived*>(base_ptr);
However, this won't always work. You need to have run-time typeid enabled and the base class needs to have at least one virtual method.
Before you go doing this, why do you need to go from a base pointer to a derived pointer? That is a clue that you may need to rethink your design.
There is only one object, it is composed of a Base and a Derived- that is, the Base is put into memory right next to the Derived, in most implementations. That means that the Base* is not the same as Derived* in the general case, but they will be very close.
Now, you can trivially obtain the Base* from the Derived*, the cast is implicit, but you can also make it explicit:
Derived* dptr = ...;
Base* ptr = dptr;
However, there is nothing stopping a single derived object from containing multiple Base objects. Usually this is not the case, but it can happen. That means that you cannot compare Base pointers and expect to know if you are dealing with the same object, only the same Base subobject.
In the simple case of single inheritance, with most compilers:
If you've got a pointer to the derived class, then that's the same as the pointer to the base class. Both pointers have the same value and point to the same memory address.
In memory, if you create an instance of a derived class, it will be laid out as the members of the base object, followed by the members of the derived object. The base class members form part of the derived object.
class Base
{
int b;
};
class Derived : public Base
{
int d;
};
In memory, say the Derived pointer is 0400. Then:
0400 byte 1 of b
0401 byte 2 of b
0402 byte 3 of b
0403 byte 4 of b
0404 byte 1 of d
0405 byte 2 of d
0406 byte 3 of d
0407 byte 4 of d
The derived object consists of the base members and derived's own members, and the address of both of these starts at 0400.
It just so happens, that at 0400, the base object part of derived is located. So, base and derived have the same address.

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.