gpt4 book ai didi

c++ - 为什么VS2013在下面的第一个和第二个例子中分别使用了非虚拟调用和虚拟调用?

转载 作者:太空宇宙 更新时间:2023-11-04 11:33:32 25 4
gpt4 key购买 nike

第一个例子: 纯虚函数 foo()Base 构造函数中通过非虚调用调用。这解释了为什么代码正常执行,即它不像第二个示例那样中止。

#include <iostream>
struct Base {
Base() { foo(); }
virtual void foo() = 0;
};

void Base::foo() { std::cout << "Base::foo()\n"; }

struct Derived : Base { void foo() { std::cout << "Derived::foo()\n"; } };

int main()
{
Derived d;
}

第二个例子:这里纯虚函数 foo() 也在 Base 构造器中被调用,但是有一个虚调用和代码中止 R6025 - 纯虚函数调用

#include <iostream>

struct Base {
Base() { call_foo(); }
virtual void foo() = 0;
void call_foo() { foo(); }
};

void Base::foo() { std::cout << "Base::foo()\n"; }

struct Derived : Base { void foo() { std::cout << "Derived::foo()\n"; } };

int main()
{
Derived d;
}

我从 §10.4/6 了解到,从构造函数或析构函数调用的纯虚函数被视为未定义行为。但我很好奇,对于这两个片段中对 foo() 的不同调用,什么是合理的解释?

最佳答案

在第一种情况下,直接从构造函数调用函数,动态类型在编译时已知,因此不需要虚拟分派(dispatch)。编译器可以生成对 Base::foo 的直接调用。

在第二种情况下,从另一个函数调用它,该函数可以随时调用派生自 Base 的任何类型,动态类型在编译时是未知的,因此需要虚拟分派(dispatch)。

如您所说,这是未定义的行为;原则上,任何一种情况都可能发生任何事情。我希望在第一种情况下有一个编译器警告(GCC 给出了一个);但在第二种情况下,错误只能在运行时检测到(如果有的话)。

关于c++ - 为什么VS2013在下面的第一个和第二个例子中分别使用了非虚拟调用和虚拟调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23681392/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com