2

The following code contains several header files in which classes are defined: area, circle, ring, rectangle, pattern. area is the basis class, circle is a derivation. ring and rectangle are derivations of circle and pattern is a derivation of both circle and rectangle, describing a geometrical figure of a coloured circle, which contains a rectangle shaped hole. The class area defines a variable color which due to the double derivation will be contained in pattern twice. Anyways, I hope I can state this question in a way that you can follow along!

Consider this code:

int main() {
    area *list[8];
    ring blue_ring("BLUE",5,2);
    pattern blue_pattern("BLUE",30,5,5);
    list[0]=&blue_ring;
    list[4]=static_cast<circle *>(&blue_pattern);
    return 0;
}

What I don't understand is the cast in the third last line. The object blue_pattern is of the type pattern. Well and the pointer array list stores addresses pointing to objects of the type area. So why do I have to convert blue_pattern to an object of type circle. This is an example from a programming beginners book. It says in there that the cast is necessary because the object pattern contains data from area twice. But I don't understand this reasoning.

Here's me trying to provide minimal code, which is just the headers:

"example0051.h"

#ifndef _AREA_
#define _AREA_
class area {
public: 
    area(char * n);
    ~area();
    void getColor() const;
private: 
    char color[11];
};

#endif 

"example0052.h"

#ifndef _CIRCLE_
#define _CIRCLE_
#include "example0051.h"

class circle : public area {
public: 
    circle(char * n, float a);
    ~circle();

    float calculateArea() const;
private: 
    float radius;
};

#endif

"example0054.h"

#ifndef _RECTANGLE_
#define _RECTANGLE_
#include "example0051.h"

class rectangle : public area {
public: 
    rectangle(char * n, float a, float b);
    ~rectangle();
    float calculateArea() const;
private:
    float length;
    float width;
};

#endif

"example0055.h"

#ifndef _PATTERN_
#define _PATTERN_
#include "example0052.h"  // circle
#include "example0054.h" // rectangle

class pattern : public circle, public rectangle {
public: pattern(char * n, float a, float b, float c);
        ~pattern();
        float calculateArea() const;
};

#endif
  • 4
    Instead of only describing your classes and their possible inheritance hierarchy, please try to create a [Minimal, **Complete**, and Verifiable Example](http://stackoverflow.com/help/mcve) to show us. – Some programmer dude Oct 09 '17 at 10:43
  • you don't need to post the whole headers. Please don't do this. But you do need to create a [mcve]. In your case this probably means just the definitions of all the classes, **with an empty body**. Just so that it compiles and shows your problem. – bolov Oct 09 '17 at 10:44
  • 1
    Is `blue_pattern` really a child class of `circle`? Bet you a quid it ain't. – Bathsheba Oct 09 '17 at 10:44
  • 2
    there is a class that inherits from both `circle` and `rectangle`? *Independence day* ain't got nothing on you. – bolov Oct 09 '17 at 10:45
  • 3
    A beginners' book that teaches misdesigned class hierarchies and then proceeds to hack around that broken design doesn't sound like a good source to learn from. – molbdnilo Oct 09 '17 at 10:50
  • If you *don't* have the cast, what problems do you get? What does the compiler tell you? – Some programmer dude Oct 09 '17 at 10:58
  • 1
    On an unrelated note, don't use symbols with a leading underscore followed by an upper-case letter (like e.g. `_AREA_`), those are reserved. Please see [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for more details. – Some programmer dude Oct 09 '17 at 10:59
  • 1
    `#define _AREA_`, `_RECTANGLE_`, `_PATTERN_`. Those symbols are reserved to the implementation and defining them has undefined behaviour. – eerorika Oct 09 '17 at 11:01
  • IMO, `pattern` should inherit from `area` and have `circle` and `rectangle` members. – molbdnilo Oct 09 '17 at 11:07
  • I strongly suggest you find a better book. Pretty much any book on the topic is going to better than that. A pattern is a round rectangle which is an area twice over and you can calculate the area of either of those areas so the pattern has 2 areas as well as being 2 areas? Its going to be very hard to learn the concept from such a bad design. – ROX Oct 09 '17 at 11:51
  • apparently the book isn't the best. It is very light however, just intended as starting literature. –  Oct 09 '17 at 12:17

1 Answers1

2

note how your hierarchy looks like:

  area        area
   ^           ^
   |           |
   |           |
rectangle    circle
   ^           ^
    \         /
     \       /
      \     /
      pattern

So pattern * can be cast to area * in two ways. Compiler can't decide by itself which version is more valid so it will print an error.

When casting to circle * is added it is clear how to perform conversion to area *.

Probably in next step you will learn about virtual inheritance and diamond problem, but in my opinion this example is terrible and this should be resolved by composition, not by multiple inheritance.

Marek R
  • 32,568
  • 6
  • 55
  • 140
  • thx Marek, you're right btw, virtual inheritance is next... so when I cast `blue_pattern` to `circle` my object is of type `circle` now. In both classes I have defined a function `calculateArea()` and I still want to calculate the area of the pattern and not the circle. Will this work? –  Oct 09 '17 at 11:22