在成员构造函数中调用虚函数

5

我对以下行为很好奇:

#include <iostream>
#include <string>
struct A;
struct B {
    std::string b;
    B(A& a);
};
struct A {
    B member;
    virtual std::string f() { return "Hello, World!"; }
    A() : member(*this) {}
};
B::B(A& a) : b(a.f()) {}
int main() {
    std::cout << A().member.b;
}

这是否需要打印预期结果?还是未定义的行为?

1个回答

6

这是合法的。根据 §12.7 [class.cdtor]/p4:

成员函数,包括虚函数(10.3),可以在构造或析构期间(12.6.2)调用。当从构造函数或析构函数直接或间接调用虚函数,包括在构造或析构类的非静态数据成员期间,且调用适用于正在构建或析构的对象(称之为x),被调用的函数是构造函数或析构函数类中的最终覆盖者,而不是在更派生类中重写它的函数。如果虚函数调用使用显式类成员访问(5.2.5),并且对象表达式引用x或该对象的一个基类子对象的完整对象,但不是x或其基类子对象之一,则行为未定义。

这里不适用UB情况。


我从来没有搞对过...为什么它不起作用?a.f()应该指的是x的完整对象。我读错了吗? - Marco A.
@MarcoA。仅当它引用x的完整对象或该对象的基类子对象之一但不包括x或其基类子对象之一时,才会发生UB错误。在这种情况下,正在构建的相关对象是一个A,而对象表达式引用正在构建的对象,因此行为是明确定义的。 - T.C.
谢谢你的帮助:不是任何其他对象的子对象的对象称为完整对象。,所以这里的 a 不是指一个完整的对象吗? - Marco A.
1
@MarcoA。是的,a是一个完整的对象,但这里没有UB,因为它也是x - 即当前正在构建的对象。 - T.C.
还有,“仅当它引用x的完整对象或该对象的一个基类子对象但不是x或其一个基类子对象时,才会出现UB。”- 对我来说听起来一样... - David G
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接