Search code examples
c++inheritanceinitializationinitializer-listaggregate-initialization

How to solve "error C2078: too many initializers" when moving the same members from the parent class to its child?


I am facing a relatively tricky situation here that seemed quite easy at first sight. After moving those three members from the parent class Parent to its child class Child it seems that I'm no longer able to take advantage of the default constructor.

Why? And is there a way out here without having to specifically implement a Child(...) constructor. Seems counterintuitive at first... Actually I would have thought that the first example is where it fails (thinking that the Child class' constructor would overshadow the one of its parent).

struct Parent
{
    std::string mText;
    int mInt;
    bool mBool;
};

struct Child : public Parent
{
};

Child test{ "", 0, false}; // Compiles

But in this latter case, the default constructor won't be created if the members are defined in the child class.

struct Parent
{
};

struct Child : public Parent
{
    std::string mText;
    int mInt;
    bool mBool;
};

Child test{ "", 0, false}; // error C2078: too many initializers

Solution

  • You need empty braces for the base subobject in aggregate initialization. (Default constructor is irrelevant in this case, both Parent and Child are aggregate and aggregate initialization gets performed.)

    However, if the object has a sub-aggregate without any members (an empty struct, or a struct holding only static members), brace elision is not allowed, and an empty nested list {} must be used.

    Child test{ {}, "", 0, false};
    //          ^^