0

I was looking at Understanding virtual base classes and constructor calls and I understand that the most derived class will call the top-base class default constructor directly. But is there a way not to call top-base default constructor?

One example for my problem,

#include <iostream>
#include <cstdint>

////// BEGIN LIBRARY CODE
class A
{
public:
    A()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }

    A(int)
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class B : virtual public A
{
public:
    B()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class C: virtual public A
{
public:
    C()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class D: public B, public C
{
public:
    D(int x) : A(x), B(), C() // ok. works as expected
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};
////// END LIBRARY CODE


////// USER CODE BEGINS

class E: public D
{
public:
    E() : D(42) // problem, invokes A(), not A(int)
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }

    E(int x) : D(x) // same problem
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};
////// USER CODE ENDS

int main()
{
    D d(1);
    E e1,e2(42);
}

Output

A::A(int)
B::B()
C::C()
D::D(int)
A::A()
B::B()
C::C()
D::D(int)
E::E()
A::A()
B::B()
C::C()
D::D(int)
E::E(int)

Problem:

I want E to only care about D construction. But from the explanation in the beginning, if I don't add A::A(int) below, I will always use default constructor no matter how I update class D

E() : A(42), D(42) // works, but undesirable
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
}

E(int x) : A(x), D(x) // this works, but undesirable
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
}

In short, I don't want the user-code class E extending the library code class D to have to specify class A construction parameters so...

  • Is there any way it can be done by a "middle" class in the inheritance chain such as class D in my example above, to alleviate the most-derived classes from having to do so?
Community
  • 1
  • 1
thundium
  • 995
  • 4
  • 12
  • 30

1 Answers1

1

The constructor for the top-level class calls the constructors for all virtual bases. But that's no different from calling constructors for direct non-virtual bases: if you put in an explicit constructor call, that's what the compiler will use; if you don't, it will use the default constructor. So the answer is no, if the default constructor isn't appropriate, you can't avoid calling A's constructor from E.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • 1
    By changing the design, possibly class `D` could use a data member and forwarding instead of direct inheritance, and that data member could be of a class inheriting `B` and `C`. – Cheers and hth. - Alf Aug 03 '16 at 16:38
  • @Cheersandhth.-Alf as I was rewriting the OP's code to make it legible and match the question, that was what I was thinking as well. – WhozCraig Aug 03 '16 at 16:49
  • I suppose all that depends on what the question is perceived to be about. Changing a design is not an appropriate workaround for a coding problem, although running into a coding problem can be an indication of a design problem. But given the design in the question, the answer is simply no. – Pete Becker Aug 03 '16 at 16:56