C++ print函数传入子类对象时virtual虚函数未触发重写问题
问题原因分析
核心问题是发生了对象切片(Object Slicing),以下是完整问题代码:
#include<iostream> class Entity { public: virtual int get_name() { return 1; } }; class Player : public Entity { public: int m_Name; Player(const int name) { m_Name = name; } int get_name() override { return m_Name; } }; // 问题出在这个函数的形参定义 void print(Entity entity) { std::cout << entity.get_name() << std::endl; } int main() { Entity e; Player p(2); print(e); print(p); std::cin.get(); return 0; }
具体原因说明:
- 你定义的
print函数用了值传递的Entity类型作为形参,当传入派生类Player的对象p时,会触发基类Entity的拷贝构造函数,仅拷贝p中属于基类Entity的成员,派生类Player独有的m_Name成员、以及Player的虚函数表信息都会被“切掉”,最终在函数内部得到的entity本质是一个纯Entity类型的对象,和原p对象没有关系。你调试时看到的p.m_Name=2是原对象的数值,不受这次拷贝切片的影响。 - 因此调用
entity.get_name()时,不会触发多态,只会执行Entity类的get_name实现,固定返回1。 - 如果你把print的形参改成
Entity& entity(引用传递)或者Entity* entity(指针传递),就不会发生对象切片,多态机制会正常生效,传入p时就会调用Player的get_name返回2;你改成Player类型的值传递形参时,会完整拷贝整个Player对象,没有切片,自然也能正确返回2。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

