C++ 通过对基类的引用调用虚拟函数

C++ 通过对基类的引用调用虚拟函数,c++,inheritance,reference,C++,Inheritance,Reference,当我运行控制台时,此代码拒绝将适当的消息打印到控制台。使用指针而不是引用似乎有效(->而不是。)。我是OOP新手,所以如果你觉得这很可笑,请原谅我 #include <iostream> using namespace std; class instrument { public: virtual void play(){} }; class drum : public instrument { public: void play(){ cout

当我运行控制台时,此代码拒绝将适当的消息打印到控制台。使用指针而不是引用似乎有效(->而不是。)。我是OOP新手,所以如果你觉得这很可笑,请原谅我

#include <iostream>

using namespace std;

class instrument {
public:
    virtual void play(){}
};

class drum : public instrument {
public:
    void play(){
        cout << "dum, dum" << endl;
    }
};

class piano : public instrument {
public:
    void play(){
        cout << "pling" << endl;
    }
};

int main (){
    instrument i;
    piano p;
    drum d;

    instrument &pi = i;
    pi.play();  // -

    pi = p;
    pi.play();  // pling

    pi = d;
    pi.play();  // dum, dum
}
#包括
使用名称空间std;
类乐器{
公众:
虚拟void play(){}
};
鼓类:公共乐器{
公众:
无效播放(){
库特
在这里,您可以使
pi
参考
instrument
对象
i

pi = p;
这里您将
piano
对象
p
分配给
pi
引用的对象。引用
pi
不会反弹到
piano
对象。它仍然像以前一样引用相同的
instrument
对象。只是使用隐式gen为它分配了不同的内容已指定的默认赋值运算符。(在这种情况下,赋值无效,但将派生类型指定给基类型通常会导致对象切片。)当调用
pi.play()
时,引用仍然引用
instrument
对象,并且执行
instrument::play

关键是,虽然您可以获得指向不同类型的不同对象的指针,但无法对引用执行相同操作。它始终指向同一对象。您可以通过使用多个引用修复代码:

instrument &pi = i;
pi.play();  // -

instrument &pp = p;
pp.play();  // pling

instrument &pd = d;
pd.play();  // dum, dum
使用:

而不是:

virtual void play(){}

它防止了创建冗余对象的可能性。

一旦在初始化时绑定对象,就无法更改引用对象的引用。现在,启动赋值运算符(并在此过程中触发)。请回答这个问题,好吗,先生?这是一个次要问题,但你需要在基类中创建一个虚拟析构函数。@PeterWood:可能是个好主意。但不是必需的,因为他不是通过基类指针调用析构函数的。指针的可能副本比引用更通用、更灵活,不是吗?@Venom否。两者都有其用途s@Venom如果你只是考虑他们的原始功能,他们可能会更灵活。然而,你并不总是想要这样的灵活性。事实上,它甚至可能导致问题。选择适合的工作类型。是的,指针有更多的通用性和灵活性。这并不意味着它们没有用途。更好的理解?谢谢。欢迎使用StackOverflow!请在您的帖子中添加解释以补充您的代码。
int main ()
{ 
    instrument i,*pi;
    piano p;
    drum d; 
    pi= &i; 
    pi->play(); // - 
    pi = &p; 
    pi->play(); // pling
    pi = &d; 
    pi->play(); // dum, dum 
}
virtual void play(){}
int main ()
{ 
    instrument i,*pi;
    piano p;
    drum d; 
    pi= &i; 
    pi->play(); // - 
    pi = &p; 
    pi->play(); // pling
    pi = &d; 
    pi->play(); // dum, dum 
}