Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这种奇怪的多态行为需要解释_C++_Polymorphism - Fatal编程技术网

C++ 这种奇怪的多态行为需要解释

C++ 这种奇怪的多态行为需要解释,c++,polymorphism,C++,Polymorphism,我在学习多态性并尝试了一些基本的东西。在下面的代码中,我在基类Animal中有一个虚拟函数display()。我创建了两个派生类,Dog,继承自Animal,和Tommy继承自Dog。display()函数仅在一个派生类中被重写(Tommy类在下面的代码中) 在main()函数中,我通过基类指针指向派生对象 ptr = &dog; ptr->display(); 但是,它最终调用了Dog(即Animal)的父类的display()。出于好奇,我删除了其他派生类中的display(

我在学习多态性并尝试了一些基本的东西。在下面的代码中,我在基类
Animal
中有一个虚拟函数
display()
。我创建了两个派生类,
Dog
,继承自
Animal
,和
Tommy
继承自
Dog
display()
函数仅在一个派生类中被重写(
Tommy
类在下面的代码中)

main()
函数中,我通过基类指针指向派生对象

ptr = &dog;
ptr->display();
但是,它最终调用了
Dog
(即
Animal
)的父类的
display()
。出于好奇,我删除了其他派生类中的
display()
函数并检查了输出,但我得到了相同的行为,总是调用
display()父类的
。我不知道为什么会发生这种情况。我想我遗漏了一些东西。请帮助

#include <iostream>

    using namespace std;

    class Animal
    {
        protected:
            string name;
        public:
            Animal(string nam):name(nam){}

            virtual void display()const {cout<<"Base class.\n";}

        };

    class Dog : public Animal
    {
        public:
        Dog(string nam):Animal(nam){}

        };

    class Tommy : public Dog
    {
        public:
        Tommy(string nam):Dog(nam){}

        void display()const{cout<<"i am  "<<name<<endl;}
        };

    int main()
    {
        Animal *ptr;
        Dog dog("trace");
        Tommy tom("tommy");

        ptr = &dog;
        ptr->display();

        ptr = &tom;
        ptr->display();


        return 0;
        }
但是,它最终调用了Dog(即Animal)父类的display()

这完全是预期的行为,因为您没有覆盖派生类
Dog
中的虚拟函数
display

为了使派生类具有特定的行为,必须实现非纯虚拟函数
display
。您已经在
Tommy
类中实现了该函数,但在
Dog
类中没有这样的实现

但是,它最终调用了Dog(即Animal)父类的display()

这完全是预期的行为,因为您没有覆盖派生类
Dog
中的虚拟函数
display


为了使派生类具有特定的行为,必须实现非纯虚拟函数
display
。您已经在
Tommy
类中实现了该函数,但在
Dog
类中没有这样的实现。

第一次显示值时,它是Dog类型的。狗对显示没有重新定义,它使用动物的显示,因为它继承了这个功能

第二次显示值时,其类型为Tommy。Tommy重新定义了显示功能,即“我是Tommy”。它将显示此字符串,因为它重新定义了此虚拟函数

这是因为汤米是一种动物,因为汤米继承了狗,而狗继承了动物。这样想:每个汤米都是动物,但不是每个动物都是汤米或狗

虚是C++中的一个关键词,意思是函数可以在儿童类中重新定义。


编辑:只是澄清一下什么是纯虚拟函数和虚拟函数。纯虚函数表示需要在其子类中重新定义函数,否则它将无法编译(即,该函数的基类中没有实现)。虚拟函数声明可以在其子类中重新定义它(它在基类中有一个实现)。在本例中,显示是一个虚拟函数,而不是纯函数。

第一次显示值时,它是Dog类型。狗对显示没有重新定义,它使用动物的显示,因为它继承了这个功能

第二次显示值时,其类型为Tommy。Tommy重新定义了显示功能,即“我是Tommy”。它将显示此字符串,因为它重新定义了此虚拟函数

这是因为汤米是一种动物,因为汤米继承了狗,而狗继承了动物。这样想:每个汤米都是动物,但不是每个动物都是汤米或狗

虚是C++中的一个关键词,意思是函数可以在儿童类中重新定义。


编辑:只是澄清一下什么是纯虚拟函数和虚拟函数。纯虚函数表示需要在其子类中重新定义函数,否则它将无法编译(即,该函数的基类中没有实现)。虚拟函数声明可以在其子类中重新定义它(它在基类中有一个实现)。在本例中,display是一个虚拟函数,而不是纯函数。

那么,即使虚拟函数不是纯函数,我也必须重写它,这是一种强迫吗?不,当然不是。您的示例表明您不必重写它。您必须在派生类中实现纯虚函数。对于非纯虚函数,不存在派生类可以使用基类的默认实现的强制操作。@artm:您不需要在派生类中实现纯虚函数。派生类本身可以保持抽象。但在类层次结构的同一点上,您将希望得到一个具体的类,然后必须实现纯虚函数。@ChristianHackl是的,我的意思是继承层次结构中的最后一个叶类必须实现纯虚函数-正如你所说,层次结构中的中间派生类仍然可以是抽象的。那么,我必须重写虚函数,即使它不是纯函数,这是一种强迫吗?不,当然不是。您的示例表明您不必重写它。您必须在派生类中实现纯虚函数。对于非纯虚函数,不存在派生类可以使用基类的默认实现的强制操作。@artm:您不需要在派生类中实现纯虚函数。派生类本身可以保持抽象。但在类层次结构的同一点上,您将希望得到一个具体的类,然后必须实现纯虚函数。@ChristianHackl是的,我的意思是继承层次结构中的最后一个叶类必须实现纯虚函数-正如您所说,层次结构中的中间派生类仍然可以是抽象的。这就是它的方式
Base class.
i am  tommy