为什么'&'改变对象的行为?

Rav*_*noy 4 c++ oop

我正在学习C++形式Thinking in C++ V1.我遇到了一个证明继承的例子.在这里

#include <iostream>

class Instrument{
public:
    virtual void play(){
        std::cout<<"instrument::play()";
    }
};

class Wind: public Instrument{
public:
    void play(){
        std::cout<<"Wind::play()";
    }
};

void tune(Instrument& i){
    i.play();
}
int _tmain(int argc, _TCHAR* argv[])
{
    Wind flute;
    tune(flute);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Wind::play()在控制台上输出.

但是,如果我将方法'tune'更改为

void tune(Instrument i){
    i.play();
}
Run Code Online (Sandbox Code Playgroud)

输出会 instrument::play()

由于添加了'&'以便传递长笛的参考而不是副本,为什么程序输出instrument::play()而不是Wind::play()

Pet*_*ker 17

因为传递的副本有类型Instrument,而不是类型Wind,因为Instrument是函数所采用的类型.这被称为"切片".


AnT*_*AnT 7

C++中对象表达式的多态行为由其动态类型决定.

  • 附加一个参考类型的Instrument &i到类型的对象Wind,通过引用的对象的动态类型i保留.即i使用类型声明Instrument,它实际上的是类型的实际对象Wind.这就是为什么i继续表现为Wind.如果使用指针引用某个对象,情况也是如此.

    在正式的语言来说,它意味着静态类型表达的iInstrument,但动态类型,如果同样的表达Wind.出于这个原因,i表现为多态的Wind.

  • 同时,当您为类型值赋值(或初始化)对象Instrument iWind,您将创建一个独立的独立对象i类型Instrument.这个对象的类型是Instrument.因此,独立副本的i行为与Instrument所有多态上下文相同.

    再次,用正式语言说,这意味着在这种情况下,静态类型动态类型的表达式i都是Instrument.出于这个原因,i表现为多态的Instrument.

在C++语言中,"保留"对象的动态类型的唯一方法是使用指针或引用来引用该对象."Refer"是这里的关键词:您不创建新对象,而是 引用已存在的对象.并且那些现有对象继续按照其原生类型行事.类型的对象Wind继续表现为类型的对象Wind.(请注意,这仅适用于多态行为,例如,如何解析函数调用.)

但是,无论何时创建对象的独立副本(而不是引用原始对象),该副本都会获得自己的生命,具有自己的类型和相关属性.类型的独立副本Instrument与原始Wind对象无关.它没有记忆它作为一个Wind对象的副本诞生的事实.它表现得像Instrument.