早绑定场景下,为何该C++示例中变量未被正确类型识别?
为什么传入Wind对象调用tune函数却执行Instrument::play?
你遇到的问题核心是对象切片和**静态绑定(早绑定)**共同作用的结果,拆解来看:
1. 对象切片导致派生类信息丢失
你的tune函数参数是Instrument i——这是值传递。当你把Wind类型的flute传入时,编译器会创建一个Instrument类型的临时对象,只复制flute中属于Instrument基类的部分,派生类Wind特有的成员和函数信息会被"切掉"。此时tune函数里的i就是一个纯粹的Instrument对象,和原本的Wind flute已经不是同一个东西了。
2. 静态绑定(早绑定)决定了函数调用
因为Instrument::play不是虚函数,编译器在编译阶段就会根据变量的静态类型(也就是代码里声明的类型,这里i的静态类型是Instrument)确定要调用的函数,不会等到运行时去判断实际对象类型。所以不管你传入的是Wind还是其他派生类对象,只要是值传递给Instrument参数,都会调用Instrument::play。
怎么修正?
要达到你预期的调用Wind::play的效果,需要同时做两件事:
- 把
Instrument::play声明为虚函数,开启动态绑定(晚绑定):class Instrument { public: virtual void play(note) const { // 加virtual关键字 cout << "Instrument::play" << endl; } }; - 把
tune函数的参数改成引用或指针,避免对象切片:// 引用版本 void tune(Instrument& i) { i.play(middleC); } // 或者指针版本 void tune(Instrument* i) { i->play(middleC); } // 指针版本调用时要传地址:tune(&flute);
这样一来,引用/指针会保留实际对象的类型信息,加上虚函数的动态绑定,运行时就会根据对象的实际类型(Wind)调用对应的Wind::play。
内容的提问来源于stack exchange,提问作者Mezzoforte
相关产品推荐
相关产品推荐

