不同类的虚拟函数共享相同的(无效?)内存地址
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("%pn", &Class1::print);
}
};
class Class2{
public:
virtual void print(){
cout << "Class2"<<endl;
printf("%pn", &Class2::print);
}
};
class Class3{
public:
virtual void print(){
cout << "Class3"<<endl;
printf("%pn", &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 的倍数)
- 仅当使用关键字"虚拟"时,才会发生这种情况。
- 类 2 是否继承自类 1 没有任何区别。(与 2-3、1-3 等相同)
据我所知,虚拟函数是用一种叫做"vtable"的东西实现的。我知道每个类都有一个指向表的秘密指针。但即使是这样,每个函数的地址不应该是不同的,或者至少是合法的吗?
我确实研究了其他问题,例如:这个,其中函数fork()是问题的中心;这个......在看了所有关于"相同地址"的问题之后,我想,也许这与操作系统有关?但在此之后,我找不到任何相关的东西。
TL;博士:
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("%pn", (void*)&Class1::print);
}
};
class Class2{
public:
virtual void print(){
cout << "Class2"<<endl;
printf("%pn", (void*)&Class2::print);
}
};
class Class3{
public:
virtual void print(){
cout << "Class3"<<endl;
printf("%pn", (void*)&Class3::print);
}
};
int main(){
Class1 c1;
Class2 c2;
Class3 c3;
c1.print();
c2.print();
c3.print();
}
输出
Class1
0x400b50
Class2
0x400be0
Class3
0x400c70
相关文章:
- 在 Microsoft Access SQL 中调用自定义 DLL 函数时传递的内存地址无效
- 获取进程内存信息失败,错误 6 句柄无效
- 其他线程堆栈上的可用内存无效
- 不同类的虚拟函数共享相同的(无效?)内存地址
- 调用 GetPointerFrameTouchInfo时出现错误 998(对内存位置的无效访问)
- VerQueryValueA 在资源块之外写入无效内存
- Realloc():即使使用malloc()分配内存,旧大小也无效
- JNA 参数问题:内存访问无效
- Valgrind 未显示使用不正确的 c_str() 的无效内存访问
- JNA无效的内存访问
- 发生 JNI 调用 c++ dll "不满意链接错误: 对内存位置的无效访问"
- 只要我不使用它,我是否可以安全地创建对可能无效内存的引用?
- 为什么在realloc之后字符串在内存中变得无效
- 我的代码中真的有无效的内存访问吗
- 释放内存失败:free():下一个大小无效(快速):
- 赋值运算符重载和无效内存
- C++捕获无效内存异常
- 指针间接检查无效内存访问和分段错误
- 是指向无效内存时sizeof(*ptr)未定义的行为
- 什么可以使不更改地址的 Win32 C++指针突然指向无效内存?