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

C++中栈分配变量的虚方法为何未按预期工作?

为什么栈分配对象与指针的多态行为不同?

先看你定义的类:

class Entity {
public:
    virtual std::string getName() {
        return "Entity";
    }
};

class Player : public Entity {
private:
    std::string name_;
public:
    Player(const std::string& name): name_(name) {}

    std::string getName() {
        return name_;
    }
};

栈分配代码的问题:对象切片

运行这段栈分配代码时:

void print(const std::string& msg) {
    std::cout << msg << std::endl;
}

int main () {
    Player player("hello");
    print(player.getName());

    Entity e = player;
    print(e.getName());
}

实际输出是:

hello
Entity

问题出在Entity e = player;这一行——这里发生了对象切片:

  • Player作为派生类,内存布局包含基类Entity的部分,加上自己的成员name_。
  • 当把Player对象赋值给基类Entity的栈对象时,只会复制基类部分的数据,派生类特有的name_会被丢弃,最终e是一个独立的Entity对象,和原来的Player无关。
  • 此时调用e.getName(),因为e是Entity类型的实例,即便基类函数是虚函数,也不会触发多态,直接执行基类的getName方法。

指针代码符合预期的原因

使用指针的代码:

int main () {
    Player* player = new Player("hello");
    std::cout << player->getName() << std::endl;

    Entity* e = player;
    std::cout << e->getName() << std::endl;
    return 0;
}

输出符合预期:

hello
hello

原因是:

  • 基类指针e并没有复制对象,只是指向了Player对象的内存地址,不存在切片问题。
  • 因为getName是虚函数,C++会通过对象的虚函数表(vtable),找到实际指向的Player类的getName方法,从而实现多态调用。

栈对象实现多态的正确写法

如果想在栈上实现多态,不要用值赋值,改用引用:

int main () {
    Player player("hello");
    print(player.getName());

    Entity& e = player; // 使用引用绑定到Player对象
    print(e.getName());
}

引用不会复制对象,只是作为原对象的别名,因此不会发生切片,调用e.getName()时会触发多态,返回"hello"。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:10:10