An interface definition can declare zero or more base interfaces. For example
$interface IShape
{
float64 GetArea() const;
float64 GetPerim() const;
};
$interface IColouredShape : IShape
{
int32 GetColour() const;
};
$interface ICircle : IShape
{
float64 GetRadius() const;
};
$interface IColouredCircle : IColouredShape, ICircle
{
};
This allows us to speak of the subinterfaces and superinterfaces of a given interface. The interfaces form a directed acyclic graph according to the subinterface relation.
Now consider the following struct in straight C++
class ColouredCircle
{
public:
ColouredCircle() : r(3.0), c(17) {}
float64 GetArea() const {return 3.14*r*r;}
float64 GetPerim() const {return 2*3.14*r;}
float64 GetRadius() const {return r;}
int32 GetColour() const {return c;}
private:
float64 r;
int32 c;
};
This can be coerced into an IColouredCircle as follows
ColouredCircle c;
ptr<IColouredCircle> p = &c;
The pointer p can be implicit upcast to a ptr<IShape>, ptr<IColouredShape> or ptr<ICircle>.
Let a subinterface refer to either a directly or indirectly inherited interface. For example, the subinterfaces of IColouredCircle are IShape, IColouredShape, ICircle.
An interface inherits all the methods from its subinterfaces. A pointer to an interface can be implicit upcast to a pointer to any subinterface.
Sideways or downwards casting of interface pointers requires a qicast<> but is only supported for interfaces that inherit from IObject (this is described below).
Repeated inheritance is supported, but only indirectly. The following is not permitted
$interface Ix {};
$interface Iy : Ix, Ix {} // compiler error
For the purpose of comparison, consider the following code using subclassing, where it has been assumed that virtual inheritance should always be used for interface inheritance:
struct IShape
{
virtual float64 GetArea() const = 0;
virtual float64 GetPerim() const = 0;
};
struct IColouredShape : public virtual IShape
{
virtual int32 GetColour() const = 0;
};
struct ICircle : public virtual IShape
{
virtual float64 GetRadius() const = 0;
};
struct IColouredCircle : public virtual IColouredShape, public virtual ICircle
{
};
class ColouredCircle : public IColouredCircle
{
public:
ColouredCircle() : r(3.0), c(17) {}
float64 GetArea() const {return 3.14*r*r;}
float64 GetPerim() const {return 2*3.14*r;}
float64 GetRadius() const {return r;}
int32 GetColour() const {return c;}
private:
float64 r;
int32 c;
};
For the Microsoft Visual C++ compiler (VC 2008), the size of ColouredCircle is 56 bytes. That is an enormous overhead considering the member variables only take up 12 bytes.