Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.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++_Class_Polymorphism_Virtual_Undefined Behavior - Fatal编程技术网

C++ 当中间类跳过实现时,在继承层次结构中执行哪个虚拟方法?

C++ 当中间类跳过实现时,在继承层次结构中执行哪个虚拟方法?,c++,class,polymorphism,virtual,undefined-behavior,C++,Class,Polymorphism,Virtual,Undefined Behavior,我肯定以前有人问过这个问题,但我就是不知道该搜索什么。所以,一旦有人给我指出一个类似的问题,我很乐意把这个问题去掉。如果有人有更好的建议,我也很乐意将这些问题重命名为:-) 我想知道以下代码是由标准定义的行为,还是与编译器/平台相关: struct A { virtual void f() { std::cout << "A::f()" << std::endl; } }; struct B : public A { //

我肯定以前有人问过这个问题,但我就是不知道该搜索什么。所以,一旦有人给我指出一个类似的问题,我很乐意把这个问题去掉。如果有人有更好的建议,我也很乐意将这些问题重命名为:-)

我想知道以下代码是由标准定义的行为,还是与编译器/平台相关:

struct A
{
    virtual void f()
    {
        std::cout << "A::f()" << std::endl;
    }
};

struct B : public A
{
    // f() is not implemented here
};

struct C : public B
{
    virtual void f() override
    {
        B::f(); // call f() of direct base class although it is not implemented there
        std::cout << "C::f()" << std::endl;
    }
};

int main()
{
    A* pA = new C();
    pA->f();
}
编译器是否会在层次结构中向上搜索,直到找到一个实现?你能链接到C++标准吗?我通过在纯虚拟中生成f()来测试它,链接器很好地告诉我有一个未解析的符号。我可以相信吗

据我所知,使用像B::f()这样的范围操作符总是调用非虚拟版本。所以从来没有多态性发生过,是吗


编辑:如果打印语句有误导性,则将“B::f()”替换为“C::f()”

指针的动态类型

A* pA = new C();
C*

因此类C中的虚函数被调用

struct C : public B
{
    virtual void f() override
    {
        B::f(); // call f() of direct base class although it is not implemented there
        std::cout << "B::f()" << std::endl;
    }
};
调用类A中定义的虚函数。也就是说,指向类B的虚拟函数的指针表包含在类A中定义的函数的地址

在这个电话里

B::f();
可以访问类B的虚拟函数表,该表包含类A中函数定义的地址,因为该函数在类B中未被重写

<>从C++标准(5.2.2函数调用)

  • …如果所选函数是非虚拟函数,或者如果类成员访问表达式中的id表达式是限定id,则该函数 被称为。否则,它的最终重写器(10.3)在动态类型中 调用对象表达式的类型;这种呼叫称为呼叫 虚拟函数调用。[

  • 这就是所谓的虚拟或动态分派。这里有一个指向wiki的链接还有另一个有趣的链接:@AlexG我认为动态分派意味着在层次结构中动态选择虚拟方法,基本上可以启用多态性。我想,非虚拟基方法的查找与此无关。这不是“非虚拟基方法”。非虚拟基方法将是“void foo()”。如果它被标记为虚拟,即使它属于基类,那么它将被视为虚拟并创建vftable。现在,如果子类不重写或“替换”“基类的方法,它将调用基类中的方法。我认为Vlad在他的回答中比我解释得更好。你是对的,但我缺少了一个词,即不调用多态性而调用虚拟方法。我想这只是一个“direkt方法调用”,就像我在写时所做的那样:B;B.f();//也只是调用a::f()谢谢您的回复。请您再仔细考虑我的问题,并详细地说明每一个问题(参考C++标准,范围运算符,……)1):::(:)()(基本上与B,B,B())相同。;对吗?2)你能给我指出标准中的一个部分吗?许多著名的框架实际上生成了类似于OP示例的代码。这是定义良好的标准行为和实用性。基本上在任何OO GUI框架中,用户代码都应该调用覆盖内覆盖的一个基本重载。
            B::f(); // call f() of direct base class although it is not implemented there
    
    B::f();