0
votes

I'm having a problem with the constructors of a very complex class structure that is spread over several files. Each class has a public default contructor without arguments and a protected contructor with arguments. Each constructor of any derived class is calling the protected constructor of it's parent with arguments. The following example is the same for all derived classes in the structure (the number of parent classes may differ).

file example.h:

class SomeDerivedClass : virtual public SomeParentClass, virtual public SomeOtherParentClass {
public:
    SomeDerivedClass();
protected:
    SomeDerivedClass(int value);
}

file example.cpp:

SomeDerivedClass::SomeDerivedClass() : SomeParentClass(0), SomeOtherParentClass(0) {
    printf("SomeDerivedClass\n");
}
SomeDerivedClass::SomeDerivedClass(int value) : SomeParentClass(value), SomeOtherParentClass(value) {
    printf("SomeDerivedClass(%d)\n", value);
}

When I construct a class, all the direct virtual parents are constructed with the protected constructor that has arguments. But even though that protected construcor of the parents should also call the protected constructor of it's own virtual parents, the grandparents are always constructed with the default constructor.

Minimal example:

#include <stdio.h>

class Base {
public:
  Base() { printf("Base()\n"); }
  ~Base() {}
protected:
  Base(int value) { printf("Base(%d)\n", value); }
};

class Derived1 : virtual public Base {
public:
  Derived1() : Base(0) { printf("Derived1()\n"); }
  ~Derived1() {}
protected:
  Derived1(int value) : Base(value) { printf("Derived1(%d)\n", value); }
};

class Derived2 : virtual public Derived1 {
public:
  Derived2() : Derived1(0) { printf("Derived2()\n"); }
  ~Derived2() {}
protected:
  Derived2(int value) : Derived1(value) { printf("Derived2(%d)\n", value); }
};

int main() {
  Derived2* NewDerived2 = new Derived2();
}

Result:

Base()
Derived1(0)
Derived2()
1
Please provide a minimal (simplified) example demonstrating the problem.ecatmur
In C++, all "virtual parents" are always "direct". There are no "virtual grandparents", which is what I think you're doing. That's how virtual inheritance works. Virtually inherited classes are always the parent's of the most-derived class, which directly inherits them, whether explicitly declared as such, or not. C++ does not work any other way.Sam Varshavchik
@SamVarshavchik yes that works fine in minimal example. I've already tried it on real problem and I get "Base is not a direct or virtual base of Derived2"bugblatterbeast
@SamVarshavchik what I meant is: Calling Base constructor from Derived2 works fine on minimal example. On real problem I get error "Base is not a direct or virtual base of Derived2"bugblatterbeast
You failed to show the "real problem" in that case, since the shown code does not produce this compilation error, but actually runs and my comment actually perfectly explains why the results are what they are. It's unlikely anyone can help you explain a problem with code that's not even shown, but with only some other, working code being shown instead.Sam Varshavchik

1 Answers

0
votes

The Answer is given in the comments by Sam Varshavchik.

The concept of passing the argument from each constructor to it's direct parent was the wrong way of handling the issue.

I was under the wrong impression, that I can only access the direct parents of each class. Sam Varshavchik's comment helped me to see the real problem and look for it in the right places. In one of the many classes, there was one non-virtual inheritance that made it impossible to access the constructor of the base class.