-1

I'm having trouble with C++ classes and inheritance right now...

Let's say we have

Class A {
A(string name);
    ~A();
    void func(void);
}
Class B : public A {
    B(string name);
    ~B();
    ...
}
Class C : public A {
    C(string name);
    ~C();
    ...
}
Class D : public B, public D {
    D(string name);
    ~D();
    ...
}

Whenever I create D, it calls the constructor for B and the one for C which results in multiple instances of A. The compiler then says it doesn't know which "func" it should call, the one from B or the one from C.

I would like to know how to call A constructor ONLY ONCE and then use it to build B and C.

I already tried using B::func() to be able to call func() but has I must have a cout in the class A builder. It results in wrong output.

wohlstad
  • 12,661
  • 10
  • 26
  • 39
Sinews
  • 13
  • 1
  • 1
    Search for virtual inheritance. – wohlstad Jan 23 '23 at 10:26
  • 2
    Do you mean `Class D : public B, public D ` or `class D : public B, public C `? – doctorlove Jan 23 '23 at 10:26
  • 1
    This is the common [*diamond inheritance pattern*](https://www.makeuseof.com/what-is-diamond-problem-in-cpp/). – Some programmer dude Jan 23 '23 at 10:27
  • I doubt, that creation of D would invoke any constructor of C as there is no connection between them at all. Maybe it´s a typo in your question in class D constructor? – A. L Jan 23 '23 at 10:31
  • Read more about [virtual inheritance](https://en.cppreference.com/w/cpp/language/derived_class). – Ivan Venkov Jan 23 '23 at 10:31
  • your code is riddled with typos and compiler errors. Fwiw, you can call `B::func`, no problem, https://godbolt.org/z/dnEeMqqcr – 463035818_is_not_an_ai Jan 23 '23 at 10:42
  • This is a classic design problem with diamond inheritance : [The diamond problem](https://en.wikipedia.org/wiki/Multiple_inheritance). And I would advise you to look for a different design. Look in the mitigation section on that page. – Pepijn Kramer Jan 23 '23 at 11:15
  • I would expect that any C++ textbook that gives such a practice problem would explain the specific C++ concept that works like this. Also it's completely unclear what exactly is being asked about, this can be interpreted as a question about one of two different core C++ fundamentals. What is the topic of this chapter in your C++ textbook where this coding problem is from? – Sam Varshavchik Jan 23 '23 at 12:18

1 Answers1

2

This is called the diamond inheritance pattern.
In order to avoid having 2 instances of A in D, you need to use virtual inheritance.
When classes e.g. B virtually inherit A, it means that A will be present only once in a class derived from those classes.
Note: in this case it is the responsibility of the most derived class to initialize the virtual base(s) - as shown below.

The output from the following code demonstrates it:

#include <iostream>
#include <string>

class A {
public:
    A(std::string const & name) { std::cout << "A::A\n"; };
    ~A() {};
    void func(void);
};
//--------vvvvvvv-----------
class B : virtual public A {
public:
    B(std::string const& name) : A(name) { std::cout << "B::B\n"; };
    ~B() {};
};
//--------vvvvvvv-----------
class C : virtual public A {
public:
    C(std::string const& name) : A(name) { std::cout << "C::C\n"; };
    ~C() {};
};
class D : public B, public C {
public:
//-------------------------------vvvvvvv---------------------------------------------
    D(std::string const& name) : A(name), B(name), C(name) { std::cout << "D::D\n"; };
    ~D() {};
};

int main()
{
    D d("aaa");
}

Output:

A::A
B::B
C::C
D::D

I.e. A is present once in D.

Note that if you remove the virtual keyword, the output will be:

A::A
B::B
A::A
C::C
D::D

I.e. A is present twice in D (as you observed).


Some side notes:

  1. Better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
  2. Your code contains many typos: Class should be class, missing ; at the end of classes.
  3. You constructors can accept the name by const & as demonstrated in my code, to avoid copy.
wohlstad
  • 12,661
  • 10
  • 26
  • 39