这是在接受采访时向我提出的一个问题......
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!
任何人都可以解释一下吗?
答案 0 :(得分:1)
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;
}
输出:
A::f()
A::g()
B::f()
B::g()
B::f()
B::g()
A::f()
A::g()
当然,所有这些操纵都是用脚射击自己的方式。
答案 1 :(得分:1)
对这个问题的正确回答很简单:这个问题无法回答。这个问题讨论了&#34; vtable内存位置&#34;然后继续&#34;在通过构造函数&#34;创建之后。这句话没有意义,因为&#34;位置&#34;是多数,而&#34;它&#34;只能指单数。
现在,如果你有关于使用vtable指针的典型C ++实现的问题,请随时询问。我还考虑阅读The Design and Evolution of C++,其中包含一系列背景信息,供想要了解C ++如何工作以及原因的人们使用。