Topic: Avoiding ambiguities w/multiple inheritance
Author: Dick Menninger <Dick.Menninger@daytonoh.attgis.com>
Date: 1995/11/15 Raw View
I may be missing something, but
I had the distinct impression that 'using'
a base class's member function in a derived
class solves much of your problem of choosing
non-virtual functions from base classes and
does so without overhead. Of course, your
compiler needs to support it. Hopefully, VC++ 4.0
really does support it and is correct in how
it does support it.
Good Day
Dick
Dick.Menninger@DaytonOH.ATTGIS.COM
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: luc.rogge@rol.eunet.be (Luc Rogge)
Date: 1995/11/12 Raw View
I wonder: does the draft standard talk about selecting
inherited members in the case of multiple inheritance?
In the case of multiple inheritance, it is possible that more than one member
is available with the same signature. In my Visual C++ 1.52 implementation,
there are two ways to handle ambiguities:
1) redefine an item with the same signature which override the ambiguous
inherited members; in many of my designs, this item is simply a trivial call
to one of the ambiguous members. In a complex design with many inherited
classes, a lot of such trivial overloadings obfuscates the code.
2) accept the default selection via dominance; I don't like that default
because it is not trivial and because it emits a warning; I think that warning
is important because dominance is not trivial, but I don't like warnings in my
compilations, and I don't like using pragmas to shut them down (they
are not portable, they make code unreadable and they may shut down unrelated
warnings)
For example:
case (1)
class X { ...void foo(); }
class Y { ...void foo(); }
class Z : public X, public Y { ... } // does not overload foo
SomeFunction()
{
Z z;
z.foo(); // error: ambiguity: X::foo or Y::foo ?
}
Solution:
void Z::foo() { X::foo(); } // trivial overload
case (2)
class A { void foo(); }
class X : public A { void foo() }
class Y : public A {...} // does not overload foo
class Z : public X, public Y { ... }
SomeFunction()
{
Z z;
z.foo(); // warning: selecting X::foo because of dominance
}
You may say me: It's simple! Use :: operator to avoid ambiguities!
SomeFunction()
{
Z z;
z.X::foo(); // no ambiguity
}
So far, it's okay, but they are two other cases where I don't want or can use
:: to avoid ambiguity.
3) I am designer of class Z and I don't want users of my class losing their
time to guess which foo() to call (an maybe selecting the wrong one).
4) foo may be a virtual function; in the case of a late binding, there is no
way to select the right foo (It shouldn't even compile successfully)
SO: the only reasonable solution is to make what I call trivial overloadings
to avoid ambiguity. In one of my designs with a virtual function defined in a
base class inherited by many sub-classes thru multiple inheritance, such
trivial functions exceed 60% of my classes source code, obfuscating it.
Shouldn't be better to be able to manually select ambiguous members, and even
drop such dangerous things as dominant inheritance?
I don't think my design is so exotic: dominant inheritance wouldn't have been
invented if it wasn't a need for such things.
(such designs are a common thing in Eiffel, I think)
I once dreamed of a syntax to do such selection:
class Z : public X, public Y
{
void X::foo(); // do not redefine foo, but take X's implementation
...
}
This is not yet another proposal of extension, but simply a question: is it a
similar thing in the draft standard?
LuC++
P.S. In the same vein, I also dreamed of the syntax:
class Z : public X, public Y
{
void Yfoo() = Y::foo; // similar to "rename" subclause in Eiffel
}
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]