Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with the inheritance hierarchy in my example?

Tags:

c++

Here is the code:

#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';
}

I can assume that the problem (may be it's an undefined behaviour) occurred because of multiple inheritance and mutual usage of Child and Buddy. From the other side, I also have assumptions that:

  • Compiler firstly allocates memory for Child;
  • Then compiler runs Child constructor; at this point it seems to me, that compiler should know correct addresses for all 3 classes;
  • The order of initializations of classes would be: Parent, Buddy, Child. So, when the Child constructor_ is running, Buddy's memory has been already initialized, and thus Buddy can be used. I mean, Child's code can use Buddy's code, which not touches uninitialized data members of Buddy.

Which of my assumptions are correct, and which are wrong?

I use MSVS 2022 and C++14.

like image 417
qloq Avatar asked Dec 07 '25 09:12

qloq


1 Answers

This is a MSVC bug.

What seems to happen is that MSVC interprets

Child() : Buddy { *this } {}

as

Child() : Buddy { static_cast<Buddy &>(*this) } {}

Which calls the copy constructor of Buddy. That initializes parent_ with itself, which causes undefined behavior (due to reading it before its lifetime starts, which starts when the initialization is finished).

The fix is to explicitly cast to Parent &:

Child() : Buddy { static_cast<Parent &>(*this) } {}
like image 187
HolyBlackCat Avatar answered Dec 09 '25 23:12

HolyBlackCat