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

时间:2016-01-05 18:39:33

标签: 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!

任何人都可以解释一下吗?

2 个答案:

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

https://ideone.com/CEkkmN

当然,所有这些操纵都是用脚射击自己的方式。

答案 1 :(得分:1)

对这个问题的正确回答很简单:这个问题无法回答。这个问题讨论了&#34; vtable内存位置&#34;然后继续&#34;在通过构造函数&#34;创建之后。这句话没有意义,因为&#34;位置&#34;是多数,而&#34;它&#34;只能指单数。

现在,如果有关于使用vtable指针的典型C ++实现的问题,请随时询问。我还考虑阅读The Design and Evolution of C++,其中包含一系列背景信息,供想要了解C ++如何工作以及原因的人们使用。