【发布时间】:2018-04-05 12:44:12
【问题描述】:
我确信之前有人问过这个问题,但我就是不知道要搜索什么。因此,一旦有人向我指出类似的问题,我很高兴删除这个问题。如果有人有更好的建议,我也很乐意重命名问题:-)
我想知道以下代码是否是由标准定义的行为,或者这是否可能取决于编译器/平台:
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();
}
Visual Studio 2017 和 gcc 5.4.0 的输出是:
A::f()
C::f()
编译器是否会在层次结构中向上搜索直到找到实现?你能链接到 C++ 标准吗?我通过在纯虚拟中制作 f() 对其进行了测试,链接器很好地告诉我有一个未解析的符号。我可以依赖它吗?
据我了解,使用像 B::f() 这样的范围运算符总是调用非虚拟版本。所以从来没有发生过多态性,是吗?
编辑:打印语句具有误导性,将“B::f()”替换为“C::f()”。
【问题讨论】:
-
这称为虚拟或动态调度。这是维基的链接en.wikipedia.org/wiki/Dynamic_dispatch 还有另一个有趣的链接:condor.depaul.edu/ichu/csc447/notes/wk10/Dynamic2.htm
-
@AlexG 我认为动态调度意味着在层次结构中动态选择虚拟方法,这基本上可以实现多态性。我猜,查找非虚拟基础方法与此无关。
-
这不是“非虚拟基础方法”。非虚拟将是“void foo()”。如果它被标记为虚拟,即使它属于基类,它也会被视为虚拟并创建一个 vftable。现在,如果子类没有覆盖或“替换”基类的方法,它将调用基类中的方法。我认为弗拉德在他的回答中解释得比我更好。
-
你是对的,但我错过了在不调用多态性的情况下调用虚拟方法的词。我想这只是一个“直接方法调用”,就像我写的那样:B b; b.f(); // 也只是简单地调用 A::f() 而没有任何多态性。
标签: c++ class polymorphism virtual undefined-behavior