我有这个代码示例,我想了解它为什么会这样做。这是一篇介绍C ++课程中过去的试卷的问题。我现在正在攻读考试,并试图巩固我对班级继承的理解。
#include <iostream>
using namespace std;
class Bird {
public:
virtual void noise() { cout << "mumble" << endl; }
void move() { noise(); cout << "fly" << endl; }
};
class Canary: public Bird {
public:
void noise() { cout << "chirp" << endl; }
void move() { noise(); cout << "flap" << endl; }
};
class Tweety: public Canary {
public:
void noise() { cout << "tweet" << endl; }
void move() { noise(); cout << "run" << endl; }
};
int main() {
Canary *yellow = new Tweety();
yellow->noise();
yellow->move();
return 0;
}
我已运行此代码,输出为:
鸣叫 鸣叫 襟翼
这意味着它正在调用noise()的 Tweety 实现,但它正在调用move()的 Canary 实现。我很困惑。我理解多态的想法,而noise()是虚拟的,因此它调用Tweety版本是有道理的,因为* yellow是指向Tweety的指针。但为什么它称为Canary版本的move()?
我认为令我感到困惑的是这条线:
Canary *yellow = new Tweety();
这表示* yellow是一个Canary指针,指向Tweety对象。我对此很好,因为我得到指向基类的指针可以指向派生类。但*黄色指向Tweety,那为什么不使用Tweety的移动()?
提前感谢您的帮助。
答案 0 :(得分:6)
noise
是虚拟的,因此在您调用它时会动态调度到Tweety
实现。
move
非虚拟,因此要调用的版本是在编译时根据您调度通过的类型决定的。由于yellow
是Canary
,编译器会解析在编译时调用的内容,并在move
中显式调用Canary
方法。
答案 1 :(得分:1)
move()
也应该是virtual
,否则会调用指针类型的版本。
答案 2 :(得分:0)
肖恩和亚历克斯是现场。
以下是一些有助于理解不同场景的呼叫案例。
#include <iostream>
using namespace std;
class Bird {
public:
virtual void noise() { cout << "mumble" << endl; }
void move() { noise(); cout << "fly" << endl; }
void noise2() { cout << "mumble2" << endl; }
virtual void move2() { noise2(); cout << "fly2" << endl; }
};
class Canary: public Bird {
public:
void noise() { cout << "chirp" << endl; }
void move() { noise(); cout << "flap" << endl; }
void noise2() { cout << "chirp2" << endl; }
void move2() { noise2(); cout << "flap2" << endl; }
};
class Tweety: public Canary {
public:
void noise() { cout << "tweet" << endl; }
void move() { noise(); cout << "run" << endl; }
void noise2() { cout << "tweet2" << endl; }
void move2() { noise2(); cout << "run2" << endl; }
};
int main() {
Canary *yellow = new Tweety();
yellow->noise();
yellow->move();
yellow->noise2();
yellow->move2();
return 0;
}
/* OUTPUT:
tweet <- virtual dispatch
tweet <- virtual dispatch, via Bird::move()
flap <- direct call
chirp2 <- direct call
tweet2 <- direct call, from Tweety::move2()
run2 <- virtual dispatch
*/