【问题标题】:Virtual Functions of different classes share same (invalid?) memory address不同类的虚函数共享相同(无效?)内存地址
【发布时间】:2019-06-10 13:32:49
【问题描述】:

考虑以下 sn-p:

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

  • 仅当使用关键字“virtual”时才会出现这种情况。
  • Class2 是否继承自 Class1 没有任何区别。(与 2-3、1-3 等相同)

据我所知,虚函数是用一种叫做“vtable”的东西来实现的。我知道每个类都有一个指向表的秘密指针。但即使是这样,每个函数的地址不应该是不同的,或者至少是合法的吗?

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


TL;DR:

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

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

【问题讨论】:

    标签: c++ virtual-functions


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2017-12-01
      • 2022-11-29
      • 1970-01-01
      • 1970-01-01
      • 2019-05-26
      • 1970-01-01
      • 2014-10-12
      • 1970-01-01
      • 2021-11-11
      相关资源
      最近更新 更多