wally
wally

Reputation: 11002

Default base class initializer

Is there a way to specify a default initializer for a base class in the class declaration?

Say I have:

#include <string>

struct Animal {
    Animal(int legs) : legs{legs} {}
    Animal() = default;
    int legs{4};
};

struct Ant : Animal {
    Ant(int size)       : Animal{6}, size{size} {}
    Ant()               : Animal{6} {}
    Ant(std::string s)  : Animal{6} {}
    int size{0};
};

struct Spider : Animal {
    Spider(int size)       : Animal{8}, size{size} {}
    Spider()               : Animal{8} {}
    Spider(std::string s)  : Animal{8} {}
    int size{0};
};

Is there a way to specify a default base initializer similar to the default member initializer?

Something like perhaps:

#include <string>

struct Animal {
    Animal(int legs) : legs{legs} {}
    Animal() = default;
    int legs{4};
};

struct Ant : Animal{6} {
    Ant(int size)       : size{size} {}
    Ant()                {}
    Ant(std::string s)   {}
    int size{0};
};

struct Spider : Animal{8} {
    Spider(int size)       : size{size} {}
    Spider()                {}
    Spider(std::string s)   {}
    int size{0};
};

I thought about using delegating constructors, but if there are multiple bases and different constructors where the same bases are not always default initialized then delegating constructors wouldn't help to simplify in the same way as a constructor member initializer list would do for members.

Upvotes: 0

Views: 65

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595961

Is there a way to specify a default initializer for a base class in the class declaration?

To do that in the class declaration itself would require making the base class have a template parameter, eg:

template <size_t NumberOfLegs>
struct Animal {
    Animal() = default;
    int legs{NumberOfLegs};
};

struct Ant : Animal<6> {
    Ant()               = default;
    Ant(int size)       : size{size} {}
    Ant(std::string s)  {}
    int size{0};
};

struct Spider : Animal<8> {
    Spider()               = default;
    Spider(int size)       : size{size} {}
    Spider(std::string s)  {}
    int size{0};
};

But that means Animal<6> and Animal<8> are different class types, and you won't be able to pass around Ant and Spider objects where Animal is expected (without using more templates, that is).

That being said, assuming you actually want Animal to be a distinct class you can derive from and pass around, I suggest you could give your int constructors default values and omit the = default constructors (and yes, you can use delegating constructors in this example), eg:

struct Animal {
    Animal(int legs = 4) : legs{legs} {}
    int legs;
};

struct Ant : Animal {
    Ant(int size = 0)   : Animal{6}, size(size) {}
    Ant(std::string s)  : Ant(0) {}
    int size;
};

struct Spider : Animal {
    Spider(int size = 0)   : Animal{8}, size{size} {}
    Spider(std::string s)  : Spider(0) {}
    int size;
};

Upvotes: 3

Related Questions