Reputation: 152
Consider the following snippet:
#include<cstdio>
#include<iostream>
using namespace std;
class Class1{
public:
virtual void print(){
cout << "Class1"<<endl;
printf("%p\n", &Class1::print);
}
};
class Class2{
public:
virtual void print(){
cout << "Class2"<<endl;
printf("%p\n", &Class2::print);
}
};
class Class3{
public:
virtual void print(){
cout << "Class3"<<endl;
printf("%p\n", &Class3::print);
}
};
int main(){
Class1 c1;
Class2 c2;
Class3 c3;
c1.print();
c2.print();
c3.print();
}
I compiled the following code on g++(MinGW) 8.2.0, and ran the output on cmd and Powershell. (I am not sure if this matters at all.) I expected the three addresses printed to be different. However, the three addresses printed are the same, in my case '00000001', which seems weird too, because this does not sound like a valid address(not a multiple of 4)
As far as I know, virtual functions are implemented with something called a 'vtable'. I know that for each class there is a secret pointer that points to the table. But even if that is the case, shouldn't the addresses for each function be distinct, or at least legal?
I did look into other questions, such as: this, in which the function fork() was at the center of the issue; this.. and after looking at all those questions asking about "the same address" I thought, maybe this has something to do with the OS? But after this I failed to find anything relevant.
TL;DR:
1. The above code prints three same addresses. Why? How is this possible?
2. The address printed looks invalid(00000001). Why is this?
Upvotes: 1
Views: 64
Reputation: 180845
Your code has undefined behavior. &Class3::print
is a pointer to a member function, but %p
expects a void *
. If you cast the pointer to a void *
then you get valid results.
#include<cstdio>
#include<iostream>
using namespace std;
class Class1{
public:
virtual void print(){
cout << "Class1"<<endl;
printf("%p\n", (void*)&Class1::print);
}
};
class Class2{
public:
virtual void print(){
cout << "Class2"<<endl;
printf("%p\n", (void*)&Class2::print);
}
};
class Class3{
public:
virtual void print(){
cout << "Class3"<<endl;
printf("%p\n", (void*)&Class3::print);
}
};
int main(){
Class1 c1;
Class2 c2;
Class3 c3;
c1.print();
c2.print();
c3.print();
}
outputs
Class1
0x400b50
Class2
0x400be0
Class3
0x400c70
Upvotes: 3