Reputation: 1
The code snippet below explains the problem:
class base_obj_with_virtual_func
{
public:
int variable_int;
virtual void print_name() { std::cout << "Base obj " << this << std::endl; }
};
class derived_1 : public base_obj_with_virtual_func
{
public:
int variable_int_1;
void print_name() { std::cout << "Derived_1 obj " << this << std::endl; }
};
class derived_2 : public derived_1
{
public:
int variable_int_2;
void print_name() override { std::cout << "Derived_2 obj " << this << std::endl; }
};
void main()
{
derived_2 derived_2_obj;
base_obj_with_virtual_func* base_ptr = &derived_2_obj;
base_ptr->print_name(); // compiler replaces with vtable[0] lookup
// In this case, vtable[0] points to derived_2::print_name()
// Expected behavior
derived_1* derived_1_ptr = &derived_2_obj;
derived_1_ptr->print_name(); // non-virtual function. Should not cause any vtable lookup
// However, this invokes derived_2::print_name()
// Unexpected behavior
}
I was expecting output to be
Derived_2 obj XXX
Derived_1 obj XXX
However, the output is:
Derived_2 obj XXX
Derived_2 obj XXX
This output is only possible if the non-virtual method derived_1::print_name()
is causing a vTable lookup. The lookup then invokes derived_2::print_name()
Below is the object layout generated by visual-studio.
// Object layout
class derived_2 size(32):
+---
0 | +--- (base class derived_1)
0 | | +--- (base class base_obj_with_virtual_func)
0 | | | {vfptr}
8 | | | variable_int
| | | <alignment member> (size=4)
| | +---
16 | | variable_int_1
| | <alignment member> (size=4)
| +---
24 | variable_int_2
| <alignment member> (size=4)
+---
// VTable entries
derived_2::$vftable@:
| &derived_2_meta
| 0
0 | &derived_2::print_name
The vTable has only one entry. I am assuming it is corresponding to the base_obj_with_virtual_func::print_name()
This means that the non-virtual method derived_1::print_name()
doesn't have a vTable entry. But is still behaving like a virtual function!
Question = Why is non-virtual method derived_1::print_name
getting redirected to derived_2::print_name
?
Upvotes: 0
Views: 28