9

The Code is as follow :

The Code :

#include <iostream>

using namespace std;

class Animal{
   int a;

    public:
    Animal(int a) : a(a){}
    int geta(){return a;}
};

class Bird : virtual public Animal{
    string b;
    public:
    Bird(int a , string b) : Animal(a) , b(b){}
};

class Fish : virtual public Animal{
    int f;
    public:
    Fish(int a , int f) : Animal(a) , f(f){}
};

class Unknown : public Bird, public Fish{
    char u;
    public:
    Unknown(int a , int f , string b , char u )
     : Bird(a , b) , Fish(a , f) , u(u){}  //Problem
};

The Question :

1.)How am I going to initialize all the superclass if the Unknown class is instantiated?Since there's only one instance of Animal will be created , how can I avoid mysef from having to call its constructor twice ?

Thank you

log0
  • 10,489
  • 4
  • 28
  • 62
caramel1995
  • 2,968
  • 10
  • 44
  • 57
  • 1
    If you're encountering the diamond inheritance pattern in the real world, please rethink your design and see if it doesn't make more sense to use composition instead of inheritance. You should in general prefer composition to inheritance. – Rob K Sep 19 '12 at 20:17
  • 2
    @RobK Nonsense. "Diamond", or shared base classes, are common in OOP. – curiousguy Aug 18 '15 at 14:21
  • 1
    @curiousguy I'm glad I don't work on the projects you work on if you're running into diamond pattern inheritance. In 20 years of professional development in C++, I have never once needed to use it. – Rob K Aug 18 '15 at 14:41
  • 1
    @RobK What's the problem? – curiousguy Aug 18 '15 at 15:49
  • Because, as I said above, when the diamond pattern is encountered, it's usually because one is inheriting when one should be composing. It's reflective of a poor design which decreases maintainability. I won't say it's never the right thing, but I've never seen an instance where it was. – Rob K Aug 18 '15 at 17:21
  • @RobK I came here encountering the same problem when building UI classes for a firmware: On the hardware I've got buttons, I've got LEDs, and I've got buttons with an associated LED. It seemed logical to me to have a common UIElement class, an UIButtonInput and UILEDOutput derived from it, and a UILEDButton inheriting from both so I can talk to it like to any other UIElement when e.g. updating hardware and controller state in the main loop. Is this a case for diamond inheritance or why should I better compose here? – Jan Z. Sep 25 '22 at 10:45

1 Answers1

18

The most derived class initializes any virtual base classes. In your class hierarchy, Unknown must construct the virtual Animal base class (e.g. by adding Animal(a) to its initialization list).

When constructing an Unknown object, neither Fish nor Bird will call the Animal constructor. Unknown will call the constructor for the Animal virtual base.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • if i call the constructor of Animal class in the Unknown , how about the Bird and Fish ? How am I going to initialize their value respectively – caramel1995 Sep 19 '12 at 18:07
  • They will not call the `Animal` constructor: only the most derived class (`Unknown`, in this case) gets to call the constructors of any virtual base classes. – James McNellis Sep 19 '12 at 18:09
  • @JamesMcNellis How members of class bird and fish are going to set ? – Abhishek Mane Aug 06 '21 at 15:09
  • @JamesMcNellis Thanks for that simple yet insightful explanation! I wonder - why is that so? Does the virtual inheritance mechanism work this way because otherwise we would allow ambiguous values for grandparent class members (here: Animal) when we initialize the grandparent class with different members in the parent inheritance layer? – Jan Z. Sep 25 '22 at 13:28