请考虑以下代码段:
#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();
}
我在g ++(MinGW)8.2.0上编译了以下代码,并在cmd和Powershell上运行了输出。 (我不确定这是否很重要。) 我希望打印的三个地址不同。但是,打印出的三个地址是相同的,在我的情况下为“ 00000001”,这看起来也很奇怪,因为这听起来不像是有效地址(不是4的倍数)
据我所知,虚函数是通过称为“ vtable”的东西来实现的。我知道每个类都有一个指向表的秘密指针。但是,即使是那样,每个功能的地址是否也不应该不同,或者至少是合法的?
我确实调查了其他问题,例如:this,其中问题fork()处于问题的中心; this ..在查看了所有有关“相同地址”的问题后,我认为这可能与操作系统有关吗?但是之后,我找不到任何相关的东西。
TL; DR:
1。上面的代码打印三个相同的地址。为什么?这怎么可能?
2。打印的地址看起来无效(00000001)。为什么会这样?
答案 0 :(得分:3)
您的代码具有未定义的行为。 &Class3::print
是成员函数的指针,但是%p
需要void *
。如果将指针投射到void *
,则会得到有效的结果。
#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();
}
输出
Class1
0x400b50
Class2
0x400be0
Class3
0x400c70