Overloading inherited constructors

1.7k Views Asked by At

Given the following base class:

class Base {
    int a, b;
public:
    Base(int a, int b=42): a(a), b(b) { }
};

And a class that is derived from base:

class Derived: public Base {
    using Base::Base; // inherit Base constructors
    bool c;
public:
    Derived(int a): Base(a), c(true) { }
    Derived(int a, int b): Base(a, b), c(true) { }
};

Is there a way to avoid having to create two separate constructors for Derived and instead overload the inherited Base constructors to initialize the extra member of Derived?

I was thinking to use something like this:

template <typename... Args, 
    typename std::enable_if_t<std::is_constructible_v<Base, Args&&...>, int> = 0>
explicit Derived(Args&&... args):
    Base(std::forward<Args>(args)...), c(true) {}

This is close, but is too verbose and does not work if the the base class's constructors are inherited. i.e. if using Base::Base is present in the class (then it defaults to those constructors and does not initialize the field b).

It works if the base class inherited constructors are not present i.e. removing using Base::Base.


Is this the only way to have this work? i.e. by removing using Base::Base and using a variadic template constructor in each derived class? Is there a less verbose way to overload the inherited constructors?

I am using C++17.

2

There are 2 best solutions below

2
On BEST ANSWER

In this case all you need to do is provide c with an in class initializer

class Derived : public Base {
    using Base::Base;
    bool c = true;
};

allows you to use Base's constructors and will initialize c to true in all cases.

3
On

It seems like what you're looking for is a way to inherit Base's constructors while just initializing members of Derived to something specific. For that, we can use a default member initializer:

class Derived: public Base {
public:
    using Base::Base;
private:
    bool c = true;
};

Constructing a Derived(42) will invoke the Base(int) constructor, but also initialize c to true.