不同 类 的虚函数共享相同(无效?)内存地址
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 的倍数)
- 只有在使用关键字 "virtual" 时才会出现这种情况。
- Class2是否继承Class1没有区别(同2-3、1-3等)
据我所知,虚函数是用一种叫做 '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
考虑以下片段:
#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' 的东西实现的。我知道对于每个 class 都有一个指向 table 的秘密指针。但即使是这样,每个函数的地址不应该是不同的,或者至少是合法的吗?
我确实调查了其他问题,例如:
长话短说:
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