Conduit
Conduit

Reputation: 2735

C++: constructors,inheritance, and initialization

I am just beginning to learn C++, and am a little confused by the interplay of instantiation, constructor declaration, and inheritance... I think I'm beginning to wrap my head around everything, but I'd like to make sure I've conceptualized things correctly. I've provided a a class and a list of what I think is going on:

class Classy{
private:
    int foo1;
    int foo2;
public:
    //constructor 1
    Classy() { foo1 = 0; foo2 = 0; }
    //constructor 2
    Classy(int bar1) : foo1(bar1), foo2(0) {}
    //constructor 3
    Classy(int bar1, int bar2) : foo1(bar1) { foo2 = bar2; }
};

Inherited constructors can also be from a class' parent - for example:

Child(args) : Parent(args) { ...extras }

which more or less acts like Child(args) { super(args); ...extras } in the languages I'm more familiar with. If we additionally have complex properties (say prop1 is a complex classes - a string or something), then we can instantiate them with their constructors through something like this:

Child(args) : Parent(args), prop1(args) { ...extras }

Does that sum everything up properly? Are there any aspects that I'm missing, or useful elaborations on what I've stated?

Upvotes: 1

Views: 247

Answers (1)

Ben Voigt
Ben Voigt

Reputation: 283634

You're abusing the term inherited.

Those are subobject constructors, and subobjects include both member variables and base class subobjects. The word inheritance only goes with base class subobjects. The corresponding word for member subobjects is composition.

Using the ctor-initializer list is better than assignment inside the constructor body for a couple reasons:

  • It can be used for types that have no default constructor.
  • It can be used for types that can't be assigned, such as references and const member variables.
  • It is more efficient, because it doesn't require first creating state with the default constructor that simply gets replaced.

You can also use functions and arbitrary expressions when building the parameter lists for the subobject constructors -- they don't have to simply be the arguments passed to your constructor.

If you use an empty pair of parentheses, you'll get value-initialization of a sub-object, instead of default initialization. If there's a default constructor, these are the same. Otherwise, value initialization will get your subobject zeroed, while default initialization will leave an indeterminate, possibly illegal state.

In C++11, you often want to use the universal initializer syntax with {} instead of () when invoking subobject constructors.

Here's an example where these syntaxes are useful:

class Classy
{
  // private is the default access specifier for classes
    int bar[100];
    const std::array<int, 100> baz;
    static std::array<int, 100> make_array(int x)
    {
        std::array<int, 100> retval;
        for( int i = 0; i < 100; ++i )
            retval[i] = i * x;
        return retval;
    }
public:
    //constructor 1
    Classy() : bar{}, baz{} {}
    //constructor 2
    Classy(int bar1) : bar{}, baz{make_array(bar1)} {}
};

Upvotes: 1

Related Questions