Inheriting constructors

297,538

Solution 1

If your compiler supports C++11 standard, there is a constructor inheritance using using (pun intended). For more see Wikipedia C++11 article. You write:

class A
{
    public: 
        explicit A(int x) {}
};

class B: public A
{
     using A::A;
};

This is all or nothing - you cannot inherit only some constructors, if you write this, you inherit all of them. To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them.

Historically constructors could not be inherited in the C++03 standard. You needed to inherit them manually one by one by calling base implementation on your own.


For templated base classes, refer to this example:

using std::vector;
    
template<class T>
class my_vector : public vector<T> {
    public:
    using vector<T>::vector; ///Takes all vector's constructors
    /* */
};

Solution 2

Constructors are not inherited. They are called implicitly or explicitly by the child constructor.

The compiler creates a default constructor (one with no arguments) and a default copy constructor (one with an argument which is a reference to the same type). But if you want a constructor that will accept an int, you have to define it explicitly.

class A
{
public: 
    explicit A(int x) {}
};

class B: public A
{
public:
    explicit B(int x) : A(x) { }
};

UPDATE: In C++11, constructors can be inherited. See Suma's answer for details.

Solution 3

This is straight from Bjarne Stroustrup's page:

If you so choose, you can still shoot yourself in the foot by inheriting constructors in a derived class in which you define new member variables needing initialization:

struct B1 {
    B1(int) { }
};

struct D1 : B1 {
    using B1::B1; // implicitly declares D1(int)
    int x;
};

void test()
{
    D1 d(6);    // Oops: d.x is not initialized
    D1 e;       // error: D1 has no default constructor
}

note that using another great C++11 feature (member initialization):

 int x = 77;

instead of

int x;

would solve the issue

Solution 4

You have to explicitly define the constructor in B and explicitly call the constructor for the parent.

B(int x) : A(x) { }

or

B() : A(5) { }

Solution 5

How about using a template function to bind all constructors?

template <class... T> Derived(T... t) : Base(t...) {}
Share:
297,538

Related videos on Youtube

Paschalis Siskos
Author by

Paschalis Siskos

Software is my livelihood, my hobby, my obsession. I breathe code, and want to instill in everybody I meet a little bit of how wonderful the art can be. I constantly strive to improve, to learn, and to create the cleanest code I know how. I am language agnostic, and believe every language has appropriate uses, though my favorite is C++.

Updated on April 09, 2022

Comments

  • Paschalis Siskos
    Paschalis Siskos about 2 years

    Why does this code:

    class A
    {
        public: 
            explicit A(int x) {}
    };
    
    class B: public A
    {
    };
    
    int main(void)
    {
        B *b = new B(5);
        delete b;
    }
    

    Result in these errors:

    main.cpp: In function ‘int main()’:
    main.cpp:13: error: no matching function for call to ‘B::B(int)’
    main.cpp:8: note: candidates are: B::B()
    main.cpp:8: note:                 B::B(const B&)
    

    Shouldn't B inherit A's constructor?

    (this is using gcc)

  • Mikhail
    Mikhail over 11 years
    This is quite evil because for over a year that has been no compiler that can actually build the above code :-)
  • Jan Korous
    Jan Korous about 11 years
    @Mikhail: Both clang and g++ should now support inheriting constructors: clang.llvm.org/cxx_status.html gcc.gnu.org/projects/cxx0x.html Recommend upvoting this one as the correct answer.
  • markasoftware
    markasoftware about 10 years
    just asking, would an inherited constructor be able to access/initialize the base class's private members? Or would I have to specify them as protected?
  • entheh
    entheh over 9 years
    @Markasoftware The code setting those members still belongs to the base class. The 'using' declaration just means that B gains a constructor which calls through to A's constructor. So your members can be private :)
  • Serge Rogatch
    Serge Rogatch almost 9 years
    MSVC++ still doesn't support inheriting constructors: msdn.microsoft.com/en-us/library/hh567368.aspx
  • Suma
    Suma almost 9 years
    @SergeRogatch You are correct, but it seem to be coming eventually: blogs.msdn.com/b/vcblog/archive/2015/04/29/…
  • imallett
    imallett almost 9 years
    I am a person from the future! MSVC 2015 claims support.
  • Maxim Ky
    Maxim Ky almost 9 years
    Probably you should do it with perfect forwarding: template < typename ... Args > B( Args && ... args ) : A( std::forward< Args >( args ) ... ) {}
  • whoKnows
    whoKnows almost 9 years
    Can you use this syntax to only inherit a specific constructor?
  • Barry
    Barry almost 8 years
    And you just broke Derived's copy constructor.
  • boycy
    boycy over 7 years
    @whoKnows: No, this is all-or-nothing: en.cppreference.com/w/cpp/language/using_declaration
  • Zebrafish
    Zebrafish over 7 years
    Would Base's constructor have to be templated too? When you call Base(t...), then Base would have to be templated for whatever t is?
  • Bolpat
    Bolpat over 2 years
    Don't do the first thing and hell don't do the macro. The first part defines copy and move constructor.