Riddick
Riddick

Reputation: 349

Construction of child class with added member variable

In my program I have an abstract class from which several classes inherit. Each child class introduces a member variable to store data. I noticed that when attempting to initialize the child class, whether using aggregate initialization or initializer list, I get errors, shown below.

struct FooBase {};
struct Foo : FooBase { int value; };

int main()
{
    Foo f = {8}; // "initializer for aggregate with no elements requires explicit braces"
    Foo f{8};    // same error as above
}

I figured this is because Foo inherits the constructors from FooBase, but I have a couple questions about the behavior.

As I understand, the options would be setting the data after initialization (or making a setter method) or explicitly defining a constructor for Foo. However, specifically in the context of the last question, what happens with move and copy constructors? (Is there good practice for ensuring classes are well behaved under inheritance?)

Upvotes: 5

Views: 2025

Answers (2)

r3mus n0x
r3mus n0x

Reputation: 6154

In your example you need to provide additional empty braces to initialize base class:

Foo f = {{}, 8};
Foo f{{}, 8};

Generally speaking though, not every class can be aggregate-initialized. The class is considered to be an aggregate if it has (see the source):

  • no private or protected non-static data members
  • no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
  • no virtual, private, or protected base classes
  • no virtual member functions

Also, there is no such thing as an "aggregate constructor" and a default constructor is not related to aggregate initialization in any way.

Constructors of base classes are not inherited unless you use using Base::Base to do so. Copy and move constructors are also not inherited. They are automatically generated by the compiler for each class unless they are explicitly defined or implicitly deleted.

Upvotes: 6

Dominic Price
Dominic Price

Reputation: 1146

The default constructor is a constructor which takes no arguments and value initializes all the members of a class; a constructor which takes an int and uses it to initialize value would have to be a user-defined constructor.

Constructors are not passed onto their children. If you add the using declaration using FooBase::FooBase in the definition of Foo then all of the constructors of FooBase will become visible in Foo (although in this example this would have no effect as FooBase only contains the constructors that are provided by default).

Upvotes: 2

Related Questions