Topic: Virtual functions with different return types in MI lattice


Author: John Lilley <jlilley@empathy.com>
Date: 1997/03/05
Raw View
Marc Sherman wrote:
>
> I am mixing two 3rd party class libraries using multiple inheritance.
> There is one case where the two base classes both define a virtual
> function with the same name, but the return types are different:
>
> class Foo {
>    public : virtual int Func();
> };
>
> class Bar {
>    public : virtual void Func();
> };
>
> class FooBar: public Foo, public Bar {
>   public: virtual int Func();
> };
>
> Is this ambiguous?

Hmmm, I can't find the actual language in the standard that says so, but
I observe that Borland C++ 5.0 and MSVC++ 4.2 have the same behavior.
In the above code, they both complain about the return type mismatch,
regardless of the order in which the base classes are specified.  This
is consistent with the name lookup rules in the standard, which require
that name lookup in all non-virtual base classes occur without regard to
the order of the base classes.

If the return types of Func() are all made equal, then both Borland 5
and MSVC++ 4.2 will make FooBar::Func() override *both* base class
virtual functions, i.e.:

Foo *f = new FooBar;
Bar *b = new FooBar;
f->Func();   // FooBar::Func()
b->Func();   // Foobar::Func()

john lilley
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: marcsh@corel.ca (Marc Sherman)
Date: 1997/03/03
Raw View
I am mixing two 3rd party class libraries using multiple inheritance.
There is one case where the two base classes both define a virtual
function with the same name, but the return types are different:

class Foo
{
        public:
                virtual int Func();
};

class Bar
{
        public:
                virtual void Func();
};

The reuse of the name is not an issue -- the two Func's are designed for
the same purpose, the only difference being that Foo::Func is designed
to return an error code while Bar:Func throws an exception on failure.
I need to implement the subclass with Foo's return type:

class FooBar: public Foo, public Bar
{
        public:
                virtual int Func();
};

Is this ambiguous?  My current compiler accepts the above code, but
gives an error (Overloaded function cannot differ in return type only)
if FooBar is declared: public Bar, public Foo.  This strikes me as
wrong, though I couldn't find any discussion of this situtation in
chapter 10 [class.derived] of CD2.

Another problem with the above situation is that if I call Func through
a Bar*/Bar& which points/refers to a FooBar, I get Bar::Func, rather
than FooBar::Func.  I've solved this problem by introducing an adaptor
class between FooBar and Bar:

class BarFuncAdaptor: public Bar
{
        public:
                virtual void Func()
                {
                        int err = FuncAdaptor();
                        if(err)
                                throw err;
                };

        private:
                virtual int FuncAdaptor() = 0;
};

and implemented FuncAdaptor in FooBar:

int FooBar::FuncAdaptor()
{ return Func(); } // calls int FooBar::Func()

This results in calls through Foo* and Bar* both (eventually) calling
FooBar::Func, with the call through Bar* throwing an exception on error,
and a call through Foo* returning a result code on error.  My compiler
(Metrowerks CW10) is happy with this,  but it still strikes me as an
unresolved ambiguity.

If this is in fact ambiguous, could you please provide a reference to
the DWP, so that I can report the bug to my vendor?  Thanks in advance
for any information.

- Marc
marcsh@corel.ca
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/03/09
Raw View
Marc Sherman wrote:
>
> I am mixing two 3rd party class libraries using multiple inheritance.
> There is one case where the two base classes both define a virtual
> function with the same name, but the return types are different:
>
> class Foo
> {
>         public:
>                 virtual int Func();
> };
>
> class Bar
> {
>         public:
>                 virtual void Func();
> };
>
> The reuse of the name is not an issue -- the two Func's are designed for
> the same purpose, the only difference being that Foo::Func is designed
> to return an error code while Bar:Func throws an exception on failure.
> I need to implement the subclass with Foo's return type:
>
> class FooBar: public Foo, public Bar
> {
>         public:
>                 virtual int Func();
> };
>
> Is this ambiguous?

No, Func (try to) override both Foo::Func and Bar::Func (remeber
that return type is NOT part of the function signature).

But you can't override some void Func with a int Func, so the
code is not correct.

> My current compiler accepts the above code, but
> gives an error (Overloaded function cannot differ in return type only)
> if FooBar is declared: public Bar, public Foo.  This strikes me as
> wrong, though I couldn't find any discussion of this situtation in
> chapter 10 [class.derived] of CD2.
>
> Another problem with the above situation is that if I call Func through
> a Bar*/Bar& which points/refers to a FooBar, I get Bar::Func, rather
> than FooBar::Func.  I've solved this problem by introducing an adaptor
> class between FooBar and Bar:

That's exactly the solution in case of name clash in MI: use
an adaptator class (D&E gives an example, and the ARM too).

> class BarFuncAdaptor: public Bar
> {
>         public:
>                 virtual void Func()
>                 {
>                         int err = FuncAdaptor();
>                         if(err)
>                                 throw err;
>                 };
>
>         private:
>                 virtual int FuncAdaptor() = 0;
> };
>
> and implemented FuncAdaptor in FooBar:
>
> int FooBar::FuncAdaptor()
> { return Func(); } // calls int FooBar::Func()
>
> This results in calls through Foo* and Bar* both (eventually) calling
> FooBar::Func, with the call through Bar* throwing an exception on error,
> and a call through Foo* returning a result code on error.  My compiler
> (Metrowerks CW10) is happy with this,  but it still strikes me as an
> unresolved ambiguity.

I don't understand how you 'int FooBar::Func ()' can override
'int Foo::Func ()' but not 'void BarFuncAdaptor::Func ()' or
perhaps you don't and Foo::Func is used. And the call to Func()
in FooBar::FuncAdaptor () is ambiguous.

Note: in CW 8 the call to Func is ambiguous.

> If this is in fact ambiguous, could you please provide a reference to
> the DWP, so that I can report the bug to my vendor?  Thanks in advance
> for any information.

At Metrowerks they know the compiler is really buggy. You just have
to give them the example where order of base class makes a
difference and where something is correcly marked ambiguous in CW 8
and not in CW 10.

(And why would they want an extract from the DWP since they won't
try to really conform to it until some time ? ;-) (Note: I know
this isn't an easy task and I'm not saying the guys at Metrowerks
don't work seriously).)

--
Valentin Bonnard
mailto:bonnardv@pratique.fr
http://www.pratique.fr/~bonnardv (Informations sur le C++ en Francais)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]