Topic: Ambiguous virtual function ?
Author: werner@bau2.uibk.ac.at (Werner Benger)
Date: 18 Jan 1994 17:51:19 GMT Raw View
Hello anywhere !
The following C++-Program is the extract of a raytracing-program
where section() is used to have a raw characterisation of an object
and volumetype() describes the exact morphology of an object.
The class-structure grew from this idea. A Group of objects is used
to combine multiple objects and is used for a parallel epiped, which
is constructed from a number of planes (not shown here). A Spherical
describes all kinds of objects which may be entirely surrounded by a
sphere. It can be used to derive a single spherical object like a sphere
itself (this path is not shown here), or to describe a group of objects,
which are located in a spherical volume. This is true for a cube, therefore
class Cube is derived from both "Parallel_Epiped" and "Spherical_Group".
When class Spherical_Group is defined, some nice problems occure.
Some compilers (e.g. Watcom C++ 9.5) require the definition of
Spherical_Group::volumetype() .
This might be ok, because the virtual function Base::volumetype() is
undefined if referenced from an object of type Spherical_Group::volumetype().
It could be Group::volumetype() or Spherical::volumetype().
(Base::section() is not used in this context).
If there is an object of type Spherical_Group (or derived from it to redefine
Base::section() ) and volumetype() has not been redefined in Spherical_Group,
the call Spherical::volumetype() is ambigous and GNUC C++ 2.5.7 or
Borland C++ 3.1 complain about this. However, such an object may be derived
to class Base and the virtual function Base::volumetype() may be called.
Both GNU C and Borland C will call Spherical::volumetype().
First question to this group:
Is the call of Spherical::volumetype() a defined behaviour or
has it to be considered as a compiler bug ?
However, this case does not occure in this example program, since the object
really created is constructed from a class Cube, which has been derived from
Spherical_Group and contains a redefinition of volumetype(). Therefore
there are no more ambiguities in the effective program and Cube may savely
be converted to class Base and it's save to call Base::volumetype().
So the final question is:
Is it really required to define Spherical_Group::volumetype()
as urged by Watcom C or may it be omitted, if there is no way
to call Base::volumetype() ?
Best greetings from
Werner (werner@ast1.uibk.ac.at)
///////////////////////////////////////////////////////////////////////////////
struct Base
{
virtual char*section() = 0;
virtual char*volumetype() = 0;
};
struct Group : virtual Base
{
char*section() { return "Group"; }
char*volumetype() { return "Group"; }
};
struct Spherical : virtual Base
{
char*volumetype() { return "spherical"; }
};
struct Spherical_Group : virtual Group, Spherical
{
#ifdef __WATCOMC__
char*volumetype() { return Spherical::volumetype(); }
#endif
};
struct Parallel_Epiped : virtual Group
{
char*section() { return "Parallel Epiped"; }
};
struct Cube : Parallel_Epiped, Spherical_Group
{
char*section() { return Parallel_Epiped::section(); }
char*volumetype() { return Spherical::volumetype(); }
};
#include <stdio.h>
main()
{
Cube C;
Base &b = C;
printf("Cube is a %s %s \n",C.volumetype(),C.section());
printf("Base object is a %s %s \n",b.volumetype(),b.section());
return 0;
}