不同类的虚函数共享相同(无效?)的内存地址

时间:2019-06-10 13:32:49

标签: c++ virtual-functions

请考虑以下代码段:

#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的倍数)

  • 这仅在使用关键字“虚拟”时发生。
  • Class2是否从Class1继承没有任何区别。(与2-3、1-3等相同)

据我所知,虚函数是通过称为“ vtable”的东西来实现的。我知道每个类都有一个指向表的秘密指针。但是,即使是那样,每个功能的地址是否也不应该不同,或者至少是合法的?

我确实调查了其他问题,例如:this,其中问题fork()处于问题的中心; this ..在查看了所有有关“相同地址”的问题后,我认为这可能与操作系统有关吗?但是之后,我找不到任何相关的东西。


TL; DR:

1。上面的代码打印三个相同的地址。为什么?这怎么可能?

2。打印的地址看起来无效(00000001)。为什么会这样?

1 个答案:

答案 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