91

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?

2

6 Answers 6

132

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

Sign up to request clarification or add additional context in comments.

4 Comments

This is not working for me. I get a "No instance of constructor matches the argument list".
@charlesrockbass This means that your B2 has no constructor matches your argument list or the constructor is not in accessible visibility
How would this syntax look if you have to specify namespace? For example with the following class: struct my_container : std::vector<int>{}
@Kartoffel, 1) using base=std::vector<int>; 2) using base::base;
46

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; } 

1 Comment

Adding comment, because SO keeps suggesting it, I prefer using syntax, because it's way shorter in usual cases and seems way cleaner to me.
14

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); } 

Comments

4

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.

2 Comments

Are you sure it compiles? How is A initialized in the 1st constructor?
Ah yeah, rushed the example a little. Fixed now.
3
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; }; 

Comments

1

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 ) { } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.