lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Why is this taxonomy not a DAG?


From: Vadim Zeitlin
Subject: Re: [lmi] Why is this taxonomy not a DAG?
Date: Mon, 11 Feb 2019 19:29:19 +0100

On Mon, 11 Feb 2019 15:12:20 +0000 Greg Chicares <address@hidden> wrote:

GC> I need to implement a set of products with an "inheritance" graph
GC> like this (suspend any disbelief that we descend from fish):
GC> 
GC>           +Mermaid+
GC>           |       |
GC>        +Human+    Gills
GC>        |     |
GC>      +Fish+  Lungs
GC>      |    |
GC>   Animal  Gills

 Biology is not my strongest area, so I'm not sure if mermaids have one or
2 pairs of gills? In the inheritance graph above they have 2 of them, one
immediately inherited from and another one inherited via fish, and this is
actually the case which would work as you'd want, but I suspect that you
actually want to have only pair, which is more problematic.

GC> where all classes would have a common "zoological entity" base class.
GC> 
GC> I was hoping to use C++ inheritance to do that, with "gills" and "lungs"
GC> being mixin classes, such that a declaration like
GC>   class Mermaid : public Human : public Gills // add "virtual" as needed
GC> would suppress Lungs and provide Gills.

 Well, you can't really "suppress" anything using inheritance in C++, it's
agglomerative-only. But you can override Lungs initialization with Gills.

GC> Yet, even though C++17 (N4659)
GC> at 15.6.2/13.1 prescribes a
GC>   "depth-first left-to-right traversal of the graph of base classes"
GC> and the tree above is a graph, apparently a DAG is specifically meant,
GC> as the traversal order is not
GC>   Animal, Gills, Fish, Lungs, Human, Mermaid, Gills (again)

 This is exactly what you'd obtain with your example below modified to
exclude "virtual" from all lines using "virtual public M0", i.e. I get

        C M0 D0 M1 DX M0 DY

(condensed on one line to save vertical space), which is 1-to-1 translation
of the above.

 Of course, you do need to use simple, non-virtual, inheritance from M0 to
obtain this. The cost of doing this is to have 2 M0 sub-objects in the
object DY and getting a warning when compiling the code due to ambiguity
between them (gcc says "warning: direct base ‘M0’ inaccessible in ‘DY’ due
to ambiguity" while clang gives an as usual better: "warning: direct base
'M0' is inaccessible due to ambiguity: class DY -> class DX -> class D0 ->
class M0, class DY -> class M0"), but if this is really what you want, you
can easily have it.

 Note that you do need to keep "virtual" when inheriting from the helper
"B" ("Multicellular"?) class in your example as otherwise calling hello()
would be ambiguous. But, in principle, as long as you only use M0 for
initializing it and don't need to call any methods on it, or use any of its
fields, later, not using virtual inheritance for it would be fine.

GC> but rather
GC>   Animal, Gills, Fish, Lungs, Human, Mermaid

 This is what you get with your unmodified example due to virtual
inheritance which eliminates the duplicates of M0/Gills from the
inheritance hierarchy and how could it do anything else? You need to
construct Gills before constructing Fish and, due to the use of "virtual",
there is only one pair of Gills in Mermaid, and you can't construct an
already constructed object again.

 Sorry if I'm missing something obvious here, but I'm afraid I just don't
see how could you expect anything else from this code. You have the choice
between using or not using virtual inheritance, which should be determined
solely by the biological consideration of the gills multiplicity in the
mermaid family. But once this choice is made, the ctor behaviour is fully
determined by it and it really couldn't do anything different.


GC> I can see many ways to get the desired result. I was just hoping that
GC> C++'s multiple inheritance would work because it affords such a compact,
GC> readable framework for expressing the graph.

 Well, I'd like to mildly but decisively disagree with this. I could go
into more details if you'd like but to summarize, I think that using
inheritance is good for simple class hierarchies and the above is already
not really simple and I suspect that the actual thing you're trying to
model is even more complicated. So it certainly looks to me that something
more flexible, i.e. composition/aggregation, would be more suitable here.

GC> In the unlikely event that a concrete test case is wanted, I append the
GC> one I wrote to explore this issue

 Thank you, this was very helpful,
VZ


reply via email to

[Prev in Thread] Current Thread [Next in Thread]