Using C++ base class constructors?

121,670

Solution 1

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 2

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 3

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

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

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 )
  {
  }
Share:
121,670
minyor
Author by

minyor

Updated on January 24, 2020

Comments

  • minyor
    minyor over 4 years

    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?

  • BЈовић
    BЈовић over 12 years
    Are you sure it compiles? How is A initialized in the 1st constructor?
  • obmarg
    obmarg over 12 years
    Ah yeah, rushed the example a little. Fixed now.
  • Charles
    Charles almost 9 years
    This is not working for me. I get a "No instance of constructor matches the argument list".
  • Sergei Krivonos
    Sergei Krivonos over 8 years
    @charlesrockbass This means that your B2 has no constructor matches your argument list or the constructor is not in accessible visibility
  • Lukas Salich
    Lukas Salich over 2 years
    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.