Using C++ base class constructors?

C++InheritanceConstructorC++11

C++ Problem Overview


While working with templates I ran into a need to make a base class constructors accessible from inherited classes for object creation to decrease copy/paste operations. I was thinking to do this through using keyword in same manner with functions case, but that not work.

class A
{
public: 
    A(int val) {}
};

class B : public A
{
};

class C : public A
{
public:
    C(const string &val) {}
};

class D : public A
{
public:
    D(const string &val) {}
    using A::A;              // g++ error: A::A names constructor
};

void main()
{
    B b(10);                // Ok.   (A::A constructor is not overlapped)
    C c(10);                // error: no matching function to call to 'C::C(int)'
}

So my question: Is there any way to import a base class constructors after new ones in inherited class been declared?

Or there is only one alternative to declare new constructors and call a base ones from initializer list?

C++ Solutions


Solution 1 - C++

Yes, Since C++11:

struct B2 {
    B2(int = 13, int = 42);
};
struct D2 : B2 {
    using B2::B2;
// The set of inherited constructors is
// 1. B2(const B2&)
// 2. B2(B2&&)
// 3. B2(int = 13, int = 42)
// 4. B2(int = 13)
// 5. B2()
 
// D2 has the following constructors:
// 1. D2()
// 2. D2(const D2&)
// 3. D2(D2&&)
// 4. D2(int, int) <- inherited
// 5. D2(int) <- inherited
};

For additional information see http://en.cppreference.com/w/cpp/language/using_declaration

Solution 2 - C++

Prefer initialization:

class C : public A
{
public:
    C(const string &val) : A(anInt) {}
};

In C++11, you can use inheriting constructors (which has the syntax seen in your example D).

Update: Inheriting Constructors have been available in GCC since version 4.8.


If you don't find initialization appealing (e.g. due to the number of possibilities in your actual case), then you might favor this approach for some TMP constructs:

class A
{
public: 
	A() {}
	virtual ~A() {}
	void init(int) { std::cout << "A\n"; }
};

class B : public A
{
public:
	B() : A() {}
	void init(int) { std::cout << "B\n"; }
};

class C : public A
{
public:
	C() : A() {}
	void init(int) { std::cout << "C\n"; }
};

class D : public A
{
public:
	D() : A() {}
	using A::init;
	void init(const std::string& s) { std::cout << "D -> " << s << "\n"; }
};

int main()
{
	B b; b.init(10);
	C c; c.init(10);
	D d; d.init(10); d.init("a");

	return 0;
}

Solution 3 - C++

No, that's not how it is done. Normal way to initialize the base class is in the initialization list :

class A
{
public: 
    A(int val) {}
};

class B : public A
{
public:
  B( int v) : A( v )
  {
  }
};


void main()
{
    B b(10);
}

Solution 4 - C++

You'll need to declare constructors in each of the derived classes, and then call the base class constructor from the initializer list:

class D : public A
{
public:
    D(const string &val) : A(0) {}
    D( int val ) : A( val ) {}
};

D variable1( "Hello" );
D variable2( 10 );

C++11 allows you to use the using A::A syntax you use in your decleration of D, but C++11 features aren't supported by all compilers just now, so best to stick with the older C++ methods until this feature is implemented in all the compilers your code will be used with.

Solution 5 - C++

Here is a good discussion about superclass constructor calling rules. You always want the base class constructor to be called before the derived class constructor in order to form an object properly. Which is why this form is used

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

Solution 6 - C++

class A
{
public: 
    A(int val) {}
    A(string name) {}
};

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

Addition to other answers, in case there are several constuctors with the base class, and you just want to inherit some of them, you can delete the unwanted.

 class B : public A
 {
    using A::A;
    B(string) = delete;
 };

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionminyorView Question on Stackoverflow
Solution 1 - C++Sergei KrivonosView Answer on Stackoverflow
Solution 2 - C++justinView Answer on Stackoverflow
Solution 3 - C++BЈовићView Answer on Stackoverflow
Solution 4 - C++obmargView Answer on Stackoverflow
Solution 5 - C++jbat100View Answer on Stackoverflow
Solution 6 - C++ZhangView Answer on Stackoverflow