在构造函数分配后更改vtable内存

Change vtable memory after constructor allocation?

本文关键字:vtable 内存 构造函数 分配      更新时间:2023-10-16

这是在一次采访中问我的一个问题。。。

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之后,不可能更改它!

有人能解释一下吗?

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()

https://ideone.com/CEkkmN

当然,所有这些操作都是射中自己脚的方法。

对这个问题的正确回答很简单:这个问题无法回答。这个问题谈到了"vtable内存位置",然后继续到"通过构造函数创建之后"。这个句子没有意义,因为"locations"是复数,而"it"只能指单数。

现在,如果对使用vtable指针的典型C++实现有疑问,请随时提问。我也会考虑阅读《C++的设计与进化》,它包含了一堆背景信息,供那些想了解C++是如何工作的以及为什么工作的人使用。