0

I have a Base class A, 2 childs B and C that both inherits from A, and I have a class D that inherits from both B and C in which I want to take _a from B and _b from C without having to do a virtual method for print_a and print_b if possible

# include <iostream>

class A
{
    public:

    A(void) : { }
    ~A(void) { }

    inline void print_a(void) { std::cout << _a << std::endl; }
    inline void print_b(void) { std::cout << _b << std::endl; }


    protected:

    int _a;
    int _b;
};

class B : virtual A
{
    public:

    B(int a) : A() { _a = a, _b = 0; }
    ~B(void) { }

    protected:

    using A::_a;
    using A::_b;
};

class C : virtual A
{
    public:

    C(int b) : A() { _a = 0, _b = b; }
    ~C(void) { }

    protected:

    using A::_a;
    using A::_b;
};

class D : virtual public A, private B, private C
{
    public:

    D(void) : A(), B(5), C(5) { }
    ~D(void) { }


    private:

    using B::_a;
    using C::_b;
};

int main(void)
{
    D foo;

    foo.print_a();
    foo.print_b();
    return (0);
}

My D class is inheriting methods print_a and print_b from A and I want it to inherit _a = 5 from B and _b = 5 from C, but it doesn't work, it outputs:

0
5

Instead of:

5
5
2
  • You can fix it by changing the definition of D to class D : virtual public A, private C, private B but you are playing with fire if reordering things changes the output. Here is a sample with that change: onlinegdb.com/XOMzDDI8f Commented Jan 20, 2021 at 20:40
  • @JerryJeremiah It's my mistake, I wrote { _a = a, _b = 5; } instead of { _a = a, _b = 5; }, what I want to do is to copy member B::_a to D::_a and C::_b to D::_b Commented Jan 20, 2021 at 20:44

1 Answer 1

2

As you are using virtual for all base classes you end up with D having only one A (and not one as base of D, one as base of B and one as base of C).

The problem is with your constructors.

The constructor of a derived class calls the constructors of all base classes in the order they are given in the base class list, so in your case D::D calls:

A::A() -> _a and _b uninitialized
B::B(5)
  _a = 5
  _b = 0
C::C(5)
  _a = 0
  _b = 5

It is unclear why you are setting _a and _b multiple times in different constructors. It would be better to initialize members in the constructor's member initializer list and not assign it in a constructor body. You could for example write

A(int a, int b) : _a(a), _b(b) {}
B(int a) : A(a, 0) {}
C(int b) : A(0, b) {}
D() : A(5, 5), B(5), C(5) {}

Here D::D() would result in

A(5, 5) -> _a initialized to 5, _b initialized to 5
B(5) -> no effect (on A/_a/_b)
C(5) -> no effect (on A/_a/_b)

If you want to stick with your design and initialize the variables in the constructor bodies, you can simply add code to D::D to overwrite whatever the base class constructors set:

D() : A(), B(5), C(5) { _a=5; _b=5; }
Sign up to request clarification or add additional context in comments.

8 Comments

EDIT:Constructor B is _a = 5, _b = 0, instead of b = 5 to take only _a from b and _b from c
Okay, so then how can I do to inherit _a from B and _b from C without calling B and C constructors ? It does a syntax error
You can't inherit from a part of A, only from a complete A. What exactly is your root problem? What do you want to achieve? What is the problem with the approach I subscibed? Also you seem to misunderstand, there is no _a from B and _b from C, there is only one A with _a and _b.
What I wanted to do is to have for example a class Human, with 2 childs Warrior and Thief that would have for example a health variable set to 100 for warrior and 80 for thief, and a speed variable set to 10 for thief and 5 for warrior, and then I want to create a class SuperWarrior that would have the health of a warrior and the speed of a thief, that's why I can't initialize _a and _b in the base class
OK, that gives me a good understanding, thanks. In that case my proposed solution would work. The important part is that you don't do the assignments to _a and _b in the constructors of B and C, you need to initialze _a and _b in A::A. Give my solution a try, and if you can run it in a debugger and step through it.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.