嵌套虚函数

Nested virtual functions

鉴于以下情况:

struct A
{
  const float x;
  const float y;

  A(float x, float y)
  : x{x}, y{y} {}
};

class B
{
  public:
    B(const float& floating)
    : floating{floating} {}

    virtual float foo_x() const = 0;
    virtual float foo_y() const = 0;

    virtual A foo() const
    {
      return A(foo_x(), foo_y());
    }

  protected:
    const float& floating;
};

class C : public B
{
  public:
    C(const int* integer, const float& floating)
    : B{floating}, integer{integer} {}

    virtual float foo_x() const override
    {
      return static_cast<float>(*integer) + floating + 1.0f;
    }

    virtual float foo_y() const override
    {
      return static_cast<float>(*integer) - floating - 2.0f;
    }
  private:
    const int* integer;
};

int main()
{
  float F{1.0f};
  int I{1};

  C object(&I, F);

  A res{object.foo()};
}

foo()的定义有什么问题吗?上面的代码片段产生了预期的结果(res 持有 3-2),但是在一个更大的项目中类似的设置在调用 foo() 时产生了一些意想不到的结果,同时给出如果我从 C 分别调用 foo_x()foo_y(),则输出正确(很抱歉,我无法以最小的方式重现该错误)。

我是否通过在 Bfoo() 的定义中调用 foo_x()foo_y() 来调用一些未定义的行为?在我看来,由于 foo() 最终被 C 调用,vtable 应该被正确解析,但也许我遗漏了什么。

Am I invoking some undefined behavior by calling foo_x() and foo_y() inside the definition of foo() in B?

没有。只要满足调用虚函数的所有常规先决条件,它的定义就很好,并且可以按照您期望的方式工作。

关于这些先决条件最容易犯的错误是子类 C 在这种情况下,必须在 virtual 调用之前完全构建。