我的示例中的继承层次结构有什么问题?

qlo*_*loq 17 c++

这是代码:

#include <iostream>

struct Parent
{
    virtual ~Parent() = default;
};

class Buddy
{
public:
    virtual ~Buddy() = default;
    Buddy(Parent& p) : parent_ { p } {}
    bool IsHovered() const { return is_hovered_; }

private:
    bool    is_hovered_ = false;
    Parent& parent_;
};

class Child : public Parent, public Buddy
{
public:
    Child() : Buddy { *this } {}

    bool BuddyIsHovered() const { return IsHovered(); }
};

int main()
{
    Child c;
    // Expected 'false', but 'true' is always printed.
    std::cout << std::boolalpha << c.BuddyIsHovered() << '\n';
}

Run Code Online (Sandbox Code Playgroud)

我可以假设问题(可能是未定义的行为)是由于Childand的多重继承和相互使用而发生的Buddy。从另一个角度来看,我也有这样的假设:

  • 编译器首先为Child;分配内存
  • 然后编译器运行Child构造函数;在我看来,编译器应该知道所有 3 个类的正确地址;
  • 类的初始化顺序为:Parent, Buddy, Child。所以,当Childconstructor_运行时,Buddy内存已经被初始化,因此Buddy可以使用。我的意思是,Child的代码可以使用 的Buddy代码,它不会触及 的未初始化数据成员Buddy

我的哪些假设是正确的,哪些是错误的?

我使用MSVS 2022C++14

Hol*_*Cat 19

这是一个 MSVC 错误

似乎发生的是 MSVC 解释

Child() : Buddy { *this } {}
Run Code Online (Sandbox Code Playgroud)

作为

Child() : Buddy { static_cast<Buddy &>(*this) } {}
Run Code Online (Sandbox Code Playgroud)

它调用 的复制构造函数Buddy。它会parent_自行初始化,这会导致未定义的行为(由于在其生命周期开始之前读取它,该生命周期在初始化完成时开始)。

修复方法是显式转换为Parent &

Child() : Buddy { static_cast<Parent &>(*this) } {}
Run Code Online (Sandbox Code Playgroud)

  • 我已经检查了你的修复并且它有效。你的解释是有道理的,我什至没有注意到可以调用错误的构造函数 (5认同)