C++ C+中的继承和指针+;

C++ C+中的继承和指针+;,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,我有这个代码示例,我想了解它为什么会这样做。这是一个在一个C++课程中的过去试卷的问题。我现在正在准备考试,并试图巩固我对阶级继承的理解 #include <iostream> using namespace std; class Bird { public: virtual void noise() { cout << "mumble" << endl; } void move() { noise(); cout << "f

我有这个代码示例,我想了解它为什么会这样做。这是一个在一个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;
}
这表示*黄色是一个金丝雀指针,它指向一个Tweety对象。我对此没有意见,因为我得到了指向基类的指针可以指向派生类的指针。但是*黄色指向Tweety,为什么不使用Tweety的move()


提前感谢您的帮助。

移动()也应该是虚拟的,否则将调用指针类型的版本。

移动()也应该是虚拟的,否则将调用指针类型的版本。

noise
是虚拟的,因此,当您调用它时,它被动态地分派到
Tweety
实现


move
in not virtual,因此要调用的版本在编译时根据要通过的调用类型决定。由于
yellow
是一个
Canary
编译器会解析编译时将调用的内容,并且会显式调用
Canary
中的
move
方法,因为
noise
是虚拟的,所以当您调用它时,它会动态地调度到
Tweety
实现中


move
in not virtual,因此要调用的版本在编译时根据要通过的调用类型决定。由于
yellow
是一个
Canary
,编译器会解析编译时将调用的内容,并在
Canary
中显式调用
move
方法

下面是一些更多的调用案例,它们应该有助于理解不同的场景

#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
*/
#包括
使用名称空间std;
班鸟{
公众:

虚拟虚空噪音(){coutSean和Alex很合适

下面是一些更多的调用案例,它们应该有助于理解不同的场景

#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
*/
#包括
使用名称空间std;
班鸟{
公众:

virtual void noise(){cout此示例没有多重继承。要取消对该行为的支持,您需要了解虚拟成员函数和非虚拟成员函数之间的区别。您在
金丝雀
指针上调用
移动
,而
移动
金丝雀
上不是虚拟的。我不知道小鸟“咕哝”的声音一个好的C++书应该解释一下。得到一个例子!这个例子没有多重继承。为了理解你需要理解虚拟和非虚拟成员函数之间的区别,你在代码< <代码> >代码> <代码>指针下调用<代码>移动< /COD>不是在<代码>金丝> <代码>上的虚拟。我不知道BIR。一个好的C++书应该解释一下。得到一个!1。次要的东西:我会用“编译器解决”来代替“编译器可以解决”。-因为这不是可选的,而是必需的行为。跟进/澄清问题:如果黄色是金丝雀,那么为什么虚拟函数move不调用move的金丝雀实现?您是说指针类型决定了非虚拟函数的实现,但指针指向的是什么决定了虚拟函数的实现d这是因为virtual如何与编译器一起工作,即您所称的动态调度?@Jack-
yellow
具有静态类型
Canary
。因为您通过指针调用,所以多态性将应用于您调用的任何虚拟函数。
noise
是一个虚拟函数,因此它解析为中的实现ode>Tweety
这就是
yellow
所指向的。
move
不是虚拟的,所以它是静态解析的。这意味着编译器会查看
yellow
的静态类型(a
Canary
)并调用
Canary
中的
move
函数。如果希望在运行时动态解析,则必须将
move
设置为虚拟。+1.小问题:我将“编译器可以解析”替换为“编译器确实解析”-因为这不是可选的,而是必需的行为。跟进/澄清问题:如果黄色是金丝雀,那么为什么虚拟函数move不调用move的金丝雀实现?您是说指针类型决定了非虚拟函数的实现,但指针指向的是什么决定了虚拟函数的实现d这是因为virtual如何与编译器一起工作,即您所称的动态调度?@Jack-
yellow
具有静态类型
Canary
。因为您通过指针调用,所以多态性将应用于您调用的任何虚拟函数。
noise
是一个虚拟函数,因此它解析为中的实现ode>Tweety
这就是
yellow
所指向的。
move
不是虚拟的,所以它是静态解析的。这意味着编译器会查看
yellow
的静态类型(a
Canary
)并调用
Canary
中的
move
函数。如果希望在运行时动态解析,则必须将
move
设置为虚拟。