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

Virtual Functions of different classes share same (invalid?) memory address

考虑以下片段:

#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' 的东西实现的。我知道对于每个 class 都有一个指向 table 的秘密指针。但即使是这样,每个函数的地址不应该是不同的,或者至少是合法的吗?

我确实调查了其他问题,例如:, in which the function fork() was at the center of the issue; .. 在查看了所有关于 "the same address" 的问题后,我想,也许这与 OS?但是在这之后我没能找到任何相关的东西。


长话短说:

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

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

您的代码有未定义的行为。 &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