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函数调用)
这就是所谓的虚拟或动态分派。这里有一个指向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();