c++ 中子类的子类的继承多态性

Inheritance polymorphism for subclasses of subclasses in c++

提问人:yingma 提问时间:8/17/2023 最后编辑:Vlad from Moscowyingma 更新时间:8/17/2023 访问量:62

问:

#include <iostream>

using namespace std;

class parent {
   public:
    virtual void f() { cout << "parent::f2()" << endl; }
};

class child : public parent {
   public:
    void f() { cout << "child::f()" << endl; }
};

class grandchild : public child {
   public:
    void f() { cout << "grandchild::f()" << endl; }
};

int main() {
    grandchild grandchild1;
    parent *p = &grandchild1;
    p->f();
}

上面的代码是这样运行的

grandchild::f()

在课堂上,我没有定义为虚函数。为什么仍然调用 in 类?childf()p->f()f()grandchild

C++ 继承多 态性 虚函数

评论

5赞 Yksisarvinen 8/17/2023
一旦一个函数被声明,它将存在于所有派生类中。virtualvirtual
0赞 463035818_is_not_an_ai 8/17/2023
p是指向 和 在方法中已贴花虚拟的指针。派生类不可能删除虚拟性parentparent
0赞 Yksisarvinen 8/17/2023
相关问题:stackoverflow.com/questions/3167045/... stackoverflow.com/questions/4895294/...... stackoverflow.com/questions/4024476/......(不幸的是,它们都是旧的,建议添加干净的代码而不是......virtualoverride
0赞 463035818_is_not_an_ai 8/17/2023
@Yksisarvinen我有时想知道处理这些问题的正确方法是什么。可以追溯性地将它们重新标记为(或任何适当的)。另一方面,有时最新的答案在列表的下方(stackoverflow.com/a/4026322/4117728),并且这些答案会因重新标记而失效c++03
0赞 463035818_is_not_an_ai 8/17/2023
此外,这个 stackoverflow.com/a/26375213/4117728 隐藏在许多较旧的答案后面

答:

4赞 Vlad from Moscow 8/17/2023 #1

根据 C++20 标准(虚拟函数 [class.virtual])

1 非静态成员函数是第一个虚拟函数 使用关键字 virtual 声明,或者如果它覆盖了 virtual 在基类中声明的成员函数(见下文)。

2 如果虚拟成员函数在类和 类,直接或间接派生自 Base,一个成员 函数与声明的名称、参数类型列表[dcl.fct])、cv-qualificationref-qualifier(或不存在相同)相同,然后覆盖113vfBaseDerivedvfBase::vfDerived::vfBase::vf

请注意,即使是虚函数也可以隐藏在某个中间派生类中,但它可以在后续派生类中被覆盖。

也就是说,例如,您将按以下方式更改您的类

class parent
{
public:
    virtual void f() { cout << "parent::f()" << endl; }
};

class child : public parent
{
public:
    void f( int ) { cout << "child::f()" << endl; }
};

class grandchild : public child
{
public:
    void f() { cout << "grandchild::f()" << endl; }
};

其中在类中声明的函数隐藏了类中声明的虚拟函数,但是您可以在类中覆盖它。程序输出将与原始程序相同。f( int )childf()parentgrandchild

这是一个演示程序。

#include <iostream>

using namespace std;

class parent
{
public:
    virtual void f() { cout << "parent::f()" << endl; }
};

class child : public parent
{
public:
    void f( int = 0 ) { cout << "child::f( int )" << endl; }
};

class grandchild : public child
{
public:
    void f() { cout << "grandchild::f()" << endl; }
};

int main()
{
    grandchild grandchild1;
    parent *p = &grandchild1;
    p->f(); 

    child child1;
    p = &child1;
    p->f();
}

程序输出为

grandchild::f()
parent::f()

一些评论。对于类,在类中声明的虚函数的最终覆盖是函数。对于类,最后的 overrider 是函数。childparentparent::fgrandchildgrandchild::f

最好在虚函数的声明中始终使用说明符,例如override

class grandchild : public child
{
public:
    void f() override { cout << "grandchild::f()" << endl; }
};

在这种情况下,您的代码将更加清晰。