You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向上转型非指针对象时,vtable指针会发生什么变化?

关于C++对象切片与虚表指针的问题解答

先看第一个指针转型的示例代码:

class Parent{
public:
    int x;
    Parent(int _x) : x(_x){}
    virtual void print() const{
        cout << x << '\n';
    }
};
class Derived : public Parent{
public:
    int y;
    Derived(int _x, int _y) : Parent(_x), y(_y){}
    void print() const override{
        cout << x << ' ' << y << '\n';
    }
};
int main()
{
    Derived *a = new Derived(1, 2);
    Parent *b = a;
    b->print();
}

这里Parent* b = a是指针的向上转型,b只是指向了Derived对象a的基类部分,但整个对象的本质还是Derived,所以b间接指向的虚表指针依然属于Derived类,调用print()时会触发多态,输出1 2,这符合预期。

再看第二个非指针对象的示例:

class Parent{
public:
    int x;
    Parent(int _x) : x(_x){}
    virtual void print() const{
        cout << x << '\n';
    }
};
class Derived : public Parent{
public:
    int y;
    Derived(int _x, int _y) : Parent(_x), y(_y){}
    void print() const override{
        cout << x << ' ' << y << '\n';
    }
};
int main()
{
    Derived a(1, 2);
    Parent b = a;
    b.print();
}

这里执行Parent b = a时,发生了对象切片(Object Slicing),具体细节如下:

  • 当把Derived对象赋值给Parent对象时,编译器会调用Parent的默认拷贝构造函数,只把a对象中属于Parent类的成员(也就是x)拷贝到b里,Derived类独有的成员y会被直接丢弃。
  • b是一个独立的、纯粹的Parent类实例,它的虚表指针会被初始化为指向Parent类自己的虚表,和a的Derived虚表没有关联。
  • 所以调用b.print()时,会直接调用Parent类的print()函数,输出1。

针对你的疑问逐一明确:

  1. b的虚表指针为何没指向a的?因为b本身就是Parent类的实例,它的虚表指针从创建时就指向Parent的虚表,和a的Derived虚表无关。
  2. 虚表指针的变化:a的虚表指针始终指向Derived类的虚表;而b在初始化时,虚表指针被设置为Parent类的虚表,没有继承a的虚表指针。
  3. 根本原因:这是C++的对象切片机制导致的——基类对象的内存空间只能容纳自身定义的成员,无法承载派生类的额外内容,因此无法维持派生类的多态特性。

内容的提问来源于stack exchange,提问作者dohyunii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 16:49:56