C++ 是否在构造函数分配后更改vtable内存?
这是一个采访中问我的问题C++ 是否在构造函数分配后更改vtable内存?,c++,C++,这是一个采访中问我的问题 Is it possible to change the vtable memory locations after it's created via constructor? If yes, is it a good idea? And how to do that? If not, why not? 因为我对C++没有深入的了解,我猜,在创建它之后,不可能改变VTABLE!p> 可以解释吗? < P> C++标准没有告诉我们如何动态调度。但是vtable是最常
Is it possible to change the vtable memory locations after it's
created via constructor? If yes, is it a good idea? And how to do that?
If not, why not?
因为我对C++没有深入的了解,我猜,在创建它之后,不可能改变VTABLE!p>
可以解释吗? < P> C++标准没有告诉我们如何动态调度。但是vtable是最常见的方式 通常,对象的前8个字节用于存储指向vtable的指针,但前提是该对象至少有1个虚拟函数(否则,我们可以将这8个字节保存为其他内容)。而且在运行时无法更改vtable中的记录 但是您有memset或memcpy之类的函数,可以做任何您想做的事情(更改vtable指针) 代码示例:
#include <bits/stdc++.h>
class A {
public:
virtual void f() {
std::cout << "A::f()" << std::endl;
}
virtual void g() {
std::cout << "A::g()" << std::endl;
}
};
class B {
public:
virtual void f() {
std::cout << "B::f()" << std::endl;
}
virtual void g() {
std::cout << "B::g()" << std::endl;
}
};
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
A * p_a = new A();
B * p_b = new B();
p_a->f();
p_a->g();
p_b->f();
p_b->g();
size_t * vptr_a = reinterpret_cast<size_t *>(p_a);
size_t * vptr_b = reinterpret_cast<size_t *>(p_b);
std::swap(*vptr_a, *vptr_b);
p_a->f();
p_a->g();
p_b->f();
p_b->g();
return 0;
}
当然,所有这些操作都是向自己的脚开枪的方式。对这个问题的正确回答很简单:这个问题无法回答。问题是关于“vtable内存位置”,然后是“通过构造函数创建之后”。这个句子没有意义,因为“地点”是复数,而“它”只能指单数
现在,如果您有关于使用VTABLE指针的典型C++实现的问题,请随意问。我也会考虑阅读,它包含了一些背景信息,这些人希望理解C++是如何工作的,为什么。
简单的答案:是的。对这是自动的。答案是什么?“前8个字节”取决于指针的大小,所以它也可以是1个字节或4个字节。这不仅仅是因为内存可以被保存,而且为了与C struct layout兼容,它必须被用来存储第一个成员。@SashaMN我已经接受了你的答案。您的代码示例基本上是交换两个指针,而不是直接在vtable中更改任何内容,对吗?所以,真正的答案是,不可能操纵实际的vtable条目?如果你认为面试问题是这样问的,恐怕你错了,因为它已经做出了一个无效的假设,即vtable是在构造函数中创建的。我相信这是关于vtable指针(这是许多实现中存在的一个实现细节)是否可以更改的问题。@UlrichEckhardt-基于上述来自SashaMN的示例程序,原始vtable指针内存从未更改,对吗?只是一些局部变量被交换了?如果我的理解是正确的!!什么是“vtable指针内存”?它是指向vtable的指针还是vtable本身(通常也包含指针)?A::f()
A::g()
B::f()
B::g()
B::f()
B::g()
A::f()
A::g()