gpt4 book ai didi

c++ - 构建/销毁过程中的虚拟调用

转载 作者:太空狗 更新时间:2023-10-29 20:59:29 27 4
gpt4 key购买 nike

C++ 标准 12.7/4 说:

When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the class's non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructor's or destructor's class and not one overriding it in a more-derived class. If the virtual function call uses an explicit class member access (5.2.5) and the object expression refers to the complete object of x or one of that object's base class subobjects but not x or one of its base class subobjects, the behavior is undefined.

此文本在我检查的所有版本中都是相同的(尽管在 C++03 中是第 12.7/3 段)。

我的问题是关于短语“使用显式类成员访问权限”。可能该短语的要点是指出在构造函数/析构函数主体中,使用隐式 this-> 的虚拟调用是安全的,因为对象表达式确实引用了对象 x:

struct A;
A* p;

struct A {
A() { p = this; }
virtual ~A() { if (p == this) p = nullptr; }
virtual void f() {}
};

struct B {
B();
virtual ~B();
virtual void g() {}
};

struct C : public A, public B {
virtual void f() {}
virtual void g() {}
};

B::B() {
if (p) p->f(); // UB if `p` and `this` point at same complete object
g(); // Definitely safe, calls B::g().
}

B::~B() {
if (p) p->f(); // UB if `p` and `this` point at same complete object
g(); // Definitely safe, calls B::g().
}

int main() {
C c; // UB in B::B() and B::~B()!
}

但是如果虚函数调用在语法上不是在构造函数或析构函数的定义中,而是间接调用的呢?这个程序的行为是什么?

#include <iostream>

struct A {
virtual void f() { std::cout << "A::f()\n"; }
void h() { f(); }
};

struct B {
explicit B(A& a) { a.h(); }
};

struct C : public A, public B {
C() : A(), B(static_cast<A&>(*this)) {}
virtual void f() { std::cout << "C::f()\n"; }
};

int main() {
C c;
}

我希望在 B::B(A&) 中,调用 a.h() 与调用 a.f() 一样未定义.但是我们不能说 12.7/4 中的最后一句话适用,因为虚函数调用不使用显式类成员访问。我错过了什么吗? a.f()a.h() 真的应该在这种情况下采取不同的行动吗?是否有与此相关的缺陷报告?应该有吗?

最佳答案

9.3.1/3(在 N3485 中)说

When an id-expression (5.1) that is not part of a class member access syntax (5.2.5) and not used to form a pointer to member (5.3.1) is used in a member of class X in a context where this can be used (5.1.1), if name lookup (3.4) resolves the name in the id-expression to a non-static non-type member of some class C, and if either the id-expression is potentially evaluated or C is X or a base class of X, the id-expression is transformed into a class member access expression (5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of the . operator.

在您的第二个示例中,这意味着 A::h() 的主体被转换为 (*this).f(),从而使调用成为显式类成员访问。因此 12.7/4 的最后一行适用;行为未定义。

关于c++ - 构建/销毁过程中的虚拟调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24500386/

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