Hi,

I have a doubt regarding inheritance of base class constructor by inherited class.

I was recently going through some C++ online tutorial when I came across this piece of code:

#include <iostream>
class Foo
{
        public:
        Foo() { std::cout << "Foo's constructor" << std::endl; }
};
class Bar : public Foo
{
        public:
        Bar() { std::cout << "Bar's constructor" << std::endl; }
};

int main()
{
        // a lovely elephant ;)
        Bar bar;
}

I will quote the exact text present in the site from where I took the above code :

The object bar is constructed in two stages: first, the Foo constructor is invoked and then the Bar constructor is invoked. The output of the above program will be to indicate that Foo's constructor is called first, followed by Bar's constructor.

Now, my question is:

Will the constructor Foo() be called when an object of class Bar is declared?


This is the site from where I got the above code:
Initialization Lists in C++


Now according to the site, the constructor Foo() will be called. But as per my knowledge, this is not true since base class constructors are not inherited. But I want to confirm this.

Regards,

Dani AI

Generated

Short answer: yes — when a Bar (derived) object is created one of Foo's constructors runs to initialize the base subobject, then the derived part is initialized and finally the derived constructor body runs. That is what was getting at: the base subobject must be constructed as part of constructing the derived object. (en.cppreference.com)

That does not mean the derived class automatically “has” the base constructors as its own overloads. Pre-C++11 the usual solution is to give the derived class a constructor that takes whatever arguments and forwards them to the base (as showed). Since C++11 there is a shortcut: inherit base constructors with a using-declaration so the base signatures participate in overload resolution for the derived class. Example (different names than the thread to avoid duplicating earlier snippets):

struct Parent {
    Parent(int);
};

struct Child : Parent {
    using Parent::Parent; // inherit Parent's constructors (C++11+)
    Child() = default;    // still allowed to add custom ctors
};

See the standard explanation of the using-declaration for constructors. (en.cppreference.com)

A few important caveats: inherited constructors are not a byte-for-byte copy — default/copy/move constructors and default arguments are treated specially and some signatures are suppressed; an inherited constructor will be hidden if the derived class already declares a constructor with the same signature; inherited constructors initialize the base subobject while non-static data members of the derived class are default-initialized (or use their default member initializers). Also remember virtual bases and multiple bases are initialized in the standard-specified order (virtual bases first, then direct bases in declaration order, then members). (saco-evaluator.org.za)

Practical takeaway for the original examples: Foo’s constructor does run when building a Bar. To make a Bar accept the same parameters as a Foo, either add an explicit forwarding Bar constructor (portable) or use using Foo::Foo; on a C++11-or-later compiler (convenient but be mindful of the rules above). (en.cppreference.com)

Recommended Answers

All 4 Replies

Every derived-class object contains a base-class object as part of it. By implication, constructing a derived-class object involves constructing the base-class object as well.

Therefore, when you construct an object of type Bar, part of that construction process is to construct an object of type Foo.

The Foo constructor is not inherited in the normal sense, because if it were inherited, you would be able to override it--and you can't. One of Foo's constructors is always executed as part of constructing a Bar. All you can do is choose which constructor to execute, and which arguments to pass to it, by using a constructor initializer:

class Foo {
public:
    Foo();
    Foo(int);
    // ... (perhaps other constructors)
};

class Bar: public Foo {
public:
    Bar(): Foo(42) { }
    // ...
};

Now, if you execute

Bar b;

that will execute Bar's default constructor. That constructor has a constructor-initializer of Foo(42), which means that it will pass an argument of 42 to Foo's constructor when it executes. The fact that that argument exists, and the fact that it has type int, will select the Foo constructor that takes an int argument.

Inheritance does not come into play here.

Thanks for the reply.

Now considering the source code in your post, what will happen if I execute something like:

Bar b(12)

Which constructor will be called in this case? Will this give an error because the class Bar has no constructor of the form Bar(int) or will it instead execute the constructor Foo(int) without any error?

Also, will it be fine if I edit line#10 of your source and make it something like:

Bar(): Foo(int) { }

in order to generalize the Foo part?

Thanks for the reply.

Now considering the source code in your post, what will happen if I execute something like:

Bar b(12)

Which constructor will be called in this case? Will this give an error because the class Bar has no constructor of the form Bar(int) or will it instead execute the constructor Foo(int) without any error?

It will give an error because Bar has no constructor of the form Bar(int).


Also, will it be fine if I edit line#10 of your source and make it something like:

Bar(): Foo(int) { }

in order to generalize the Foo part?

No. A constructor initializer expects an expression, and int is not an expression.

Bar (int x) : Foo(x) {}

and then

Bar b(12);

would work fine.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.