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

时间:2013-10-09 18:01:49

标签: 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;
}

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

但如果我将方法'tune'改为

void tune(Instrument i){
    i.play();
}

输出将instrument::play()

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

5 个答案:

答案 0 :(得分:17)

因为传递的副本的类型为Instrument,而不是类型Wind,因为Instrument是该函数所采用的类型。这被称为“切片”。

答案 1 :(得分:7)

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

  • Instrument &i类型的引用附加到Wind类型的对象时,i引用的对象的动态类型为保留。即即使使用i类型声明Instrument,它实际上指的是类型为Wind的实际对象。这就是i继续表现为Wind的原因。如果使用指针引用某个对象,情况也是如此。

    在正式语言中,这意味着表达式i静态类型Instrument,但是如果相同的表达式是{em>动态类型 {1}}。出于这个原因,Wind的行为多态为i

  • 同时,当您分配(或初始化)对象Wind且值为Instrument i时,您创建了一个类型为Wind的独立独立对象i。此对象的类型为Instrument。因此,在所有多态上下文中,独立副本Instrument将表现为i

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

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

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

答案 2 :(得分:3)

这是一个名为“slicing”的问题。将Wind复制到Instrument后,它会变为Instrument

答案 3 :(得分:0)

void tune(Instrument i){
    i.play();
}

如果Instrument对象和Instrument对象将打印instrument::play

,则创建新实例

当您使用引用运算符&时,您引用了Wind类型的现有对象。

答案 4 :(得分:-2)

调用Instrument::play函数的原因是,当您传递副本时,它实际上是您传递的对象的Instrument部分,因为您slice该对象。 / p>