Inherit From 2 Common Inherits

Hi everyone,
I was wondering if I could inherit 2 classes for a third one (the first 2 classes are inherited from a mutual one).
I tried compiling such a thing, and it said something about ambiguity. Does anyone know why that is and how to solve it?
If it helps, I have Windows 8.1 and I use Code::Blocks 16.01 (latest version at the moment), which has MinGw included (gcc 4.9.2).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//this code is generic and only shows what I mean in a few words.
class shape
{
public:
    char *terrain;
};

class circle:public shape
{
public:
    int radius;
};

class line:public shape
{
public:
    int xEquation, yEquation;
};

class sector:public circle, public line
{
public:
    int arcAngle;
};

int main()
{
    sector sectorInstance;
    sectorInstance.radius=10;
    sectorInstance.xEquation=7;
    if (sectorInstance.terrain)
    {
        return 1;
    }
    return 0;
}

It says:
26|error: request for member 'terrain' is ambiguous|
4|note: candidates are: char* shape::terrain|
4|note: char* shape::terrain|

I even tried declaring terrain as a variable and not pointer, but it still says the same thing.
And when I declare:
 
class sector:public shape, public circle, public line

It says:
16|warning: direct base 'shape' inaccessible in 'sector' due to ambiguity|
(and then the line-26 error)

(since I tried declaring it as a variable as well, accessing terrain with '&' or '*' doesn't change a thing)
sector inherits from both circle and line, both of which have a member named terrain.

You need to specify which subclass's instance of terrain you want. That's the ambiguity.

Right now, the inheritance diagram appears like
1
2
3
4
5
shape shape
  |     |  
circle line
  \    /
   sector
But you probably want
1
2
3
4
5
   shape
  /     \
circle line
  \     /
  sector

The implication of the first diagram is that a sector is two distinct shapes. In order to get that to work you need to disambiguate which terrain you mean by upcasting:
static_cast<circle*>(&sectorInstance)->terrain;

While the second diagram implies that a sector is only one single shape, both a line and a circle, but only whole one shape.

In this case, a sector is likely intended as a single shape and so virtual inheritance is required to make sure that each instance of sector only contains one shared base class.
class sector:public virtual circle, public virtual line

Thanks a lot, that solved the problem.
I had thought of something like this, but I wasn't sure how to do it.
IMO. Line should not inherit from Shape. It violates the Liskov Substitution Principle (LSP)
Here is the SOLID acronym:
https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

Basically LSP says that what one can apply to one should apply to the other: Does Line have Area and Perimeter properties?

Consider this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class DrawingEntity;

class Shape : public DrawingEntity;
class Point : public DrawingEntity;
class Line : public DrawingEntity;
class Annotation : public DrawingEntity;
class Arc : public DrawingEntity;
class Dimension : public DrawingEntity; // with witness lines, arrows, quantity, units and tolerances drawn

class RegularPolygon : public Shape;
class ClosedIrregularPolygon : public Shape; 
class Circle : public Shape;
class Rectangle : public Shape;

class Sector :public Shape, public Arc;

In sort of does have, but just in my case.
I use std::string to determine 8x8 characters in console, and therefore id has a size that exists in the memory (I know it shouldn't, but it's a way of memorizing it that matches the style).
@Troaat

IMO That doesn't make any sense in the context of this Topic.
Sector: The part of a circle enclosed by two radii of a circle and their intercepted arc. A pie-shaped part of a circle
http://www.mathopenref.com/arcsector.html

So it makes more sense for class sector to contain one circle and 2 line objects or pointers to such objects
gunnerfunner wrote:
So it makes more sense for class sector to contain one circle and 2 line objects or pointers to such objects


Not disagreeing, but I hope that it is clear to everyone that containment (composition, HAS A) is different to inheritance (IS A)

To me from a data POV, an Arc and Sector are very similar things. A simple definition for an arc could be a centre point, radius, begin angle, and end angle, plus possibly calculated begin and end points for the arc. I guess the only real difference comes with the draw function.

But I am not so sure that for a Sector class having an arc and 2 lines as members would be as flexible, because the required info is already there in the Arc class, and the requirement that the end points of lines match both the centre point and begin/end of the arc respectively.

So that is why I suggested class Sector : public Shape, public Arc; - it inherits it's interface virtual functions like Area, Perimeter, and Hatch from Shape , while the definition of the shape itself comes from Arc.
Topic archived. No new replies allowed.