calling virtual functions through pointers with and without consulting the VM-table - c++

I want to take the address of a member function of a c++ class, store it in a pointer, and call the virtual function later on.
I know some things about it, but do not now how to take the address of a certain implementation of a virtual function that is NOT the implementation of the most descendent class (the actual class of the object).
Here is some sample code:
#include <iostream>
using namespace std;
class ca
{
public:
virtual void vfunc() {cout << "a::vfunc ";}
void mfunc() {cout << "a::mfunc ";}
};
class cb : public ca
{
public:
virtual void vfunc() {cout << "b::vfunc ";}
};
extern "C" int main(int, char **)
{
void (ca:: *ptr_to_vfunc)() = &ca::vfunc;
cout << sizeof(ptr_to_vfunc) << " ";
cb b;
(b.*ptr_to_vfunc)();
ca a;
(a.*ptr_to_vfunc)();
void (ca:: *ptr_to_mfunc)() = &ca::mfunc;
cout << sizeof(ptr_to_mfunc) << " ";
(a.*ptr_to_mfunc)();
}
The output is:
12 b::vfunc a::vfunc 12 a::mfunc
I am working with win32-environment, and the size of member function pointers is 3 * 32-bits values! I did not specify an object when I took the address of the member function and yet, my call invokes the most descendant class' implementation of vfunc().
1) What is going on here? Why 12 bytes in stead of 4?
2) How can I take the address of ca::vfunc() and call it on b, like I normaly would do with b.ca::vfunc().

Ok: Its doing exactly what it it is supposed to do.
But to answer you questions:
1) What is going on here? Why 12 bytes in stead of 4?
Why not.
The standard does not specify a size.
I am not sure why you expect a normal pointer to be 4.
If the question is "why is a method pointer larger than a normal pointer?"
Because the implementation needs the extra space to hold information about the call.
2) How can I take the address of ca::vfunc() and call it on b, like I normaly would do with b.ca::vfunc().
You cant.

Related

can't get virtual function of parent class to work [duplicate]

This question already has answers here:
C++ overridden virtual function not getting called [duplicate]
(3 answers)
Closed 4 years ago.
I have a parent class with a virtual function in it, I then make a child class and define the function. I then make a vector of vectors and insert one of the child classes into it. I then try to call the virtual function and nothing outputs to the screen. I do not know why this is happening, does anyone know?
Parent Class
class insect{
public:
string type;
int food_cost;
int armor;
int damage;
insect();
void set_food_cost(int x);
void set_armor(int x);
void set_damage(int x);
virtual void attack(){} // this is the problematic function
};
Child Class
class bee: public insect{
public:
bee();
int armor;
int damage;
void set_armor(int x);
void attack();
};
void bee::attack(){
cout << "im a bee, stab stab!\n";
}
Creating Vector of Vectors
vector< vector<insect> > insects_on_board(10);
Adding a bee to the vector of vectors
void add_bee(vector< vector<insect> > &insects_on_board, int &bees){
bees++;
insects_on_board[9].push_back(bee());
}
Function Call
cout << "testing " << insects_on_board.at(9).at(0).type << endl;
insects_on_board.at(9).at(0).attack();
Output
testing B
My Question Again
so in the output im expecting to see "testing B" and then "im a bee, stab stab!"
but only the "testing B" is outputted to the screen, any ideas why the other part is not?
That's because you are storing actual insects and not any bees. Polymorphism (in its basic C++ way) works when you are doing 3 things:
Have a type hierarchy with properly defined and overridden virtual methods (like you are doing here,)
Create child instances (or a variety of parent and child instances,)
Access them through pointers (or references.)
You are missing points 2 and 3.
So, one way to fix it would be to store pointers to insect, and initialize them as either bees or plain insects, like so:
vector<vector<insect *>> insects_on_board (10, vector<insect *>(2)); // note the type
insects_on_board[9][0] = new bee;
insects_on_board[9][1] = new insect;
// Note the use of "->" instead of "."
cout << "testing " << insects_on_board[9][0]->type << endl;
insects_on_board[9][0]->attack();
// Contrast the output with the above's
cout << "testing " << insects_on_board[9][1]->type << endl;
insects_on_board[9][1]->attack();
Update:
Note that (at the basic level) any container that stores insects by value cannot contain anything else; not even classes derived from insect. All the polymorphism and stuff you read and hear about is only applicable for pointers to parent and child types (or references to them.)
So, your add_bee function should look like this:
void add_bee (vector<vector<insect *>> & insects_on_board, int & bees) {
bees++;
insects_on_board[9].push_back(new bee());
}
I've made only two changes in there: the vectors now contain pointers to insect and I'm newing the bees.

Why does adding virtual method increase class size in C++?

#include <iostream>
using namespace std;
class a {
virtual int foo() {
return 0;
}
};
class b {
int foo() {
return 0;
}
};
int main() {
cout << sizeof(b) << endl;
cout << sizeof(a) << endl;
}
Output (with g++ 4.9, -O3):
1
8
I assume the increase in size is due to adding a vpointer. But I thought the compiler would see that a is not actually deriving or being derived from anything, hence there is no need to add the vpointer?
The vpointer is needed because the compiler cannot guarantee an external (e.g. shared) library does not use a derived type. The existence-of-derived-class resolution happens at runtime.
Run-time type information. Any polymorphic class creates extra meta-data in the program to make things like typeof and dynamic_cast work. This is in addition to the virtual function table.

Change vtable memory after constructor allocation?

This was a question asked to me in an interview...
Is it possible to change the vtable memory locations after it's
created via constructor? If yes, is it a good idea? And how to do that?
If not, why not?
As i don't have that in depth idea about C++, my guess is that, it's not possible to change vtable after it's created!
Can anyone explain?
The C++ standards do not tell us how dynamic dispatch must be implemented. But vtable is the most common way.
Generally, the first 8 bytes of the object is used to store the pointer to vtable, but only if the object has at least 1 virtual function (otherwise we can save this 8 bytes for something else). And it is not possible to change the records in the vtable during run-time.
But you have memset or memcpy like functions and can do whatever you want (change the vtable pointer).
Code sample:
#include <bits/stdc++.h>
class A {
public:
virtual void f() {
std::cout << "A::f()" << std::endl;
}
virtual void g() {
std::cout << "A::g()" << std::endl;
}
};
class B {
public:
virtual void f() {
std::cout << "B::f()" << std::endl;
}
virtual void g() {
std::cout << "B::g()" << std::endl;
}
};
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
A * p_a = new A();
B * p_b = new B();
p_a->f();
p_a->g();
p_b->f();
p_b->g();
size_t * vptr_a = reinterpret_cast<size_t *>(p_a);
size_t * vptr_b = reinterpret_cast<size_t *>(p_b);
std::swap(*vptr_a, *vptr_b);
p_a->f();
p_a->g();
p_b->f();
p_b->g();
return 0;
}
Output:
A::f()
A::g()
B::f()
B::g()
B::f()
B::g()
A::f()
A::g()
https://ideone.com/CEkkmN
Of course all these manipulations is the way to shoot yourself in the foot.
The proper response to that question is simple: This question can't be answered. The question talks about the "vtable memory locations" and then continues with "after it's created via constructor". This sentence doesn't make sense because "locations" is plural while "it" can only refer to a singular.
Now, if you have a question concerning the typical C++ implementations that use a vtable pointer, please feel free to ask. I'd also consider reading The Design and Evolution of C++, which contains a bunch of background infos for people that want to understand how C++ works and why.

vtables and this pointer

I was trying to learn some more about the inner workings of vtables and vpointers, so I decided to try to access the vtable directly using some tricks. I created two classes, Base and Derv, each having two virtual functions (Derv overriding those of Base).
class Base
{
int x;
int y;
public:
Base(int x_, int y_) : x(x_), y(y_) {}
virtual void foo() { cout << "Base::foo(): x = " << x << '\n'; }
virtual void bar() { cout << "Base::bar(): y = " << y << '\n'; }
};
class Derv: public Base
{
int x;
int y;
public:
Derv(int x_, int y_) : Base(x_, y_), x(x_), y(y_) {}
virtual void foo() { cout << "Derived::foo(): x = " << x << '\n'; }
virtual void bar() { cout << "Derived::bar(): y = " << y << '\n'; }
};
Now, the compiler adds a vtable pointer to each class, occupying the first 4 bytes (32 bits) in memory. I accessed this pointer by casting the address of an object to a size_t*, since the pointer points to another pointer of size sizeof(size_t). The virtual functions can now be accessed by indexing the vpointer, and casting the result to a function pointer of the appropriate type. I encapsulated these steps in a function:
template <typename T>
void call(T *ptr, size_t num)
{
typedef void (*FunPtr)();
size_t *vptr = *reinterpret_cast<size_t**>(ptr);
FunPtr fun = reinterpret_cast<FunPtr>(vptr[num]);
//setThisPtr(ptr); added later, see below!
fun();
}
When one of the memberfunctions are called this way, e.g. call(new Base(1, 2), 0) to call Base::foo(), it is hard to predict what will happen, since they are called without a this-pointer. I solved this by adding a little templatized function, knowing that g++ stores the this-pointer in the ecx register (this however forces me to compile with the -m32 compiler flag):
template <typename T>
void setThisPtr(T *ptr)
{
asm ( mov %0, %%ecx;" :: "r" (ptr) );
}
Uncommenting the setThisPtr(ptr) line in the snippet above now makes it a working program:
int main()
{
Base* base = new Base(1, 2);
Base* derv = new Derv(3, 4);
call(base, 0); // "Base::foo(): x = 1"
call(base, 1); // "Base::bar(): y = 2"
call(derv, 0); // "Derv::foo(): x = 3"
call(derv, 1); // "Derv::bar(): y = 4"
}
I decided to share this, since in the process of writing this little program I gained more insight in how vtables work and it might help others in understanding this material a little better.
However I still have some questions:
1. Which register is used (gcc 4.x) to store the this-pointer when compiling a 64-bit binary? I tried all 64-bit registers as documented here: http://developers.sun.com/solaris/articles/asmregs.html
2. When/how is the this-pointer set? I suspect that the compiler sets the this pointer on each function call through an object in a similar way as to how I just did it. Is this the way polymorphism actually works? (By setting the this-pointer first, then calling the virtual function from the vtable?).
On Linux x86_64, and I believe other UNIX-like OSes, function calls follow the System V ABI (AMD64), which itself follows the IA-64 C++ ABI for C++. Depending on the method's type, the this pointer is either passed implicitly through first argument or the second argument (when the return value has non-trivial copy constructor or destructor, it must live as a temporary on stack, and the first argument is implicitly a pointer to that space); otherwise, virtual method calls are identical to function calls in C (integer/pointer arguments in %rdi, %rsi, %rdx, %rcx, %r8, %r9, overflowing to stack; integer/pointer return in %rax; floats in %xmm0-%xmm7; etc.). Virtual method dispatch works by looking up a pointer in the vtable then calling it just like a non-virtual method.
I'm less familiar with Windows x64 conventions, but I believe it to be similar in that C++ method calls follow the exact same structure as C function calls (which use different registers than on Linux), just with an implicit this argument first.

C++ swap problem in inheritance scenario

I want to add swap functionality to two existing C++ classes. One class inherits from the other. I want each classes' instances to only be swappable with instances of the same class. To make it semi-concrete, say I have classes Foo and Bar. Bar inherits from Foo. I define Foo::swap(Foo&) and Bar::swap(Bar&). Bar::swap delegates to Foo::swap. I want Foo::swap to only work on Foo instances and Bar::swap to only work on Bar instances: I can't figure out how to enforce this requirement.
Here's a sample of what's giving me trouble:
#include <algorithm>
#include <iostream>
struct Foo {
int x;
Foo(int x) : x(x) {};
virtual void swap(Foo &other) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::swap(this->x, other.x);
};
};
struct Bar : public Foo {
int y;
Bar(int x, int y) : Foo(x), y(y) {};
virtual void swap(Bar &other) {
std::cout << __PRETTY_FUNCTION__ << " ";
Foo::swap(other);
std::swap(this->y, other.y);
};
};
void display(Foo &f1, Foo &f2, Bar &b34, Bar &b56)
{
using namespace std;
cout << "f1: " << f1.x << endl;
cout << "f2: " << f2.x << endl;
cout << "b34: " << b34.x << " " << b34.y << endl;
cout << "b56: " << b56.x << " " << b56.y << endl;
}
int main(int argc, char **argv)
{
{
Foo f1(1), f2(2);
Bar b34(3,4), b56(5,6);
std::cout << std::endl << "Initial values: " << std::endl;
display(f1,f2,b34,b56);
}
{
Foo f1(1), f2(2);
Bar b34(3,4), b56(5,6);
std::cout << std::endl << "After Homogeneous Swap: " << std::endl;
f1.swap(f2); // Desired
b34.swap(b56); // Desired
display(f1,f2,b34,b56);
}
{
Foo f1(1), f2(2);
Bar b34(3,4), b56(5,6);
std::cout << std::endl << "After Heterogeneous Member Swap: " << std::endl;
// b56.swap(f2); // Doesn't compile, excellent
f1.swap(b34); // Want this to not compile, but unsure how
display(f1,f2,b34,b56);
}
return 0;
}
Here's the output:
Initial values:
f1: 1
f2: 2
b34: 3 4
b56: 5 6
After Homogeneous Swap:
virtual void Foo::swap(Foo&)
virtual void Bar::swap(Bar&) virtual void Foo::swap(Foo&)
f1: 2
f2: 1
b34: 5 6
b56: 3 4
After Heterogeneous Member Swap:
virtual void Foo::swap(Foo&)
f1: 3
f2: 2
b34: 1 4
b56: 5 6
You can see in the final output group where f1.swap(b34) "sliced" b34 in a potentially nasty way. I'd like the guilty line to either not compile or blow up at runtime. Because of the inheritance involved, I think I run into the same problem if I use a nonmember or friend swap implementation.
The code is available at codepad if that helps.
This use case arises because I want to add swap to boost::multi_array and boost::multi_array_ref. multi_array inherits from multi_array_ref. It only makes sense to swap multi_arrays with multi_arrays and multi_array_refs with multi_array_refs.
Swap, like assignment and comparison work well with value types and don't work well with bases of class hierarchies.
I've always found it easiest to follow the Scott Meyer's Effective C++ recommendation of not deriving from concrete classes and making only leaf classes concrete. You can then safely implement swap, operator==, etc. as non-virtual functions for leaf nodes only.
While it's possible to have a virtual swap functions the whole point of having virtual base classes is to have dynamic behaviour at runtime so I think you're on to a loser trying to get all incorrect possibilities to fail at compile time.
If you want to go the virtual swap route, then one possible approach is to do something like this.
class Base
{
public:
virtual void Swap(Base& other) = 0;
};
class ConcreteDerived
{
virtual void Swap(Base& other)
{
// might throw bad_cast, in this case desirable
ConcreteDerived& cother = dynamic_cast<ConcreteDerived&>(other);bad_cast
PrivateSwap(cother);
}
void PrivateSwap(ConcreteDerived& other)
{
// swap implementation
}
};
(Somewhat hacky solution)
Add a protected virtual method, isBaseFoo(), make it return true in Foo, and false in Bar, the the swap method for Foo could check it's argument has isBaseFoo()==true.
Evil, and detects the problem only at run-time, but I can't think of anything better, although Charles Bailey's answer might be better, if you allow dynamic_cast<>.
You cannot really do this, but I don't see the point, anyway. It's no worse than slicing on operator= or copy constructors, and you cannot avoid the latter, either. Why should swap be any different?
For the same reason, it's likely not worth it making swap virtual, for the same reason why you don't make operator= virtual.
I think that this case scenario is now addressed by the presence of move semantics in C++11.
I usually use the swap function only to avoid copy duplication in the assignments so it's only used statically, by the derived class that needs to extend the swap function and that knows the static type of its base so there is no need for virtuality (which as it was stated can lead to subtle problems with slicing). In fact I declare the swap function as a protected method in my base to make sure it's not use directly anywhere else.
The most concrete class can then have the final version public if necessary.
What you are actually trying to do is swap instances of classes from a third party inheritance hierarchy. Given that, I'd forget about using swap on the actual classes and add a level of indirection. Using boost::shared_ptr is a good approach; use shared_ptr instances containing whatever class you want, and swap to your heart's content.
In general, solving the problem as you asked it at compile time is hard for all the reasons described by the other answerers.