有关标准中虚拟功能描述的问题

时间:2020-09-21 12:24:02

标签: c++ inheritance c++17 language-lawyer virtual-functions

#include <iostream>
struct A { 
    virtual void f(){
        std::cout<<"1\n";
    } 
};
struct B : A {

};
struct C : A { 
    void f(){
        std::cout<<"abc\n";
    } 
};
struct D : B, C { 

}; 
int main(){
  D mostDerived{};
  D* ptr = &mostDerived;
  B* bptr = ptr;
  A* aptr = bptr;
  aptr->f();
}

考虑上面的代码,outcome1。但是,由于标准所说,我对此结果感到怀疑:
class.virtual#def:final_overrider

为方便起见,我们说任何虚函数都将覆盖自身。除非其中S是基类子对象的最派生类(如果有),类对象S 的虚拟成员函数C :: vf是最终的重写器。声明或继承另一个重写vf的成员函数

class.derived#def:inheritance

除构造函数外,基类的成员被称为由派生类继承。基类的构造方法也可以按照[namespace.udecl]中的描述进行继承。

IIUC,将B和A中类型C的基类子对象分别视为A1A2。在我的示例中,最派生的类是D,根据上述规则,对于类B,最终的替代者是A::f,它是从A继承的类C,最终的替代者是C::f,它是在类C中声明的,对于类D,它是从BC派生的,因此它将继承BC的这些成员。由于C::f覆盖A::f,因此根据规则unless **the most derived class of which S is a base class subobject** (if any) declares or **inherits another member function that overrides vf**,将A1视为S(即A1是...的子对象类D),其中D继承了another member function that overrides vf的{​​{1}}。这意味着,子对象C::f的最终替代应该为A1,因此,我想知道为什么不是C::f而不是abc的结果?

另一个问题是:

1

struct A { virtual void f(){ std::cout<<"1\n"; } }; struct B : A { void f(){} }; struct C : A { void f(){} }; struct D : B, C { }; B::f都覆盖了虚函数C::f,但它们彼此不覆盖,因此A::f继承了哪个功能?还是两者都由D继承?

如果我错过了什么,如何正确阅读以上规则。还是对于第一个问题,上述规则是否确实不清楚以至造成误解?

1 个答案:

答案 0 :(得分:2)

...类对象S的虚拟成员函数C :: vf是最终重写器,除非其最派生的类S是基类子对象(如果有)声明或继承另一个重写的成员函数vf。

引用的规则可能有点误导,因此可能是有缺陷的。

仅对类型为vf任何基进行覆盖B还是不够的,但是对于那基本子对象< / em>。在您的示例中,有两个类型为A的基本子对象,其中一个被A::f覆盖,另一个未被覆盖。

那么D继承哪个函数?还是两者都是D继承的?

两者都是继承的。