Search code examples
c++inheritancepolymorphism

Passing object of base class to function of reference to derived class


I'm trying to write code which can find the distance between lots of different types of shapes. I've defined a base class Shape with a virtual distance(Shape& otherShape) function to find the distance to another shape and then want to define that for all my derived classes.

The problem is that there are lots of possible pairs of shapes, so my solution was to define a set of distance functions outside the classes (circle-circle, circle-square, square-tri etc.) and then call the corresponding one from the distance function. I've added a mini example of what I mean below, with just one derived class Circle to demonstrate the problem.

When I try and call my specific circleCircleDistance function I get an error because it can't convert the base class into the derived class. Is there any way I can address this or will my design as it stands just not work?

enum ShapeType{CIRCLE, SQUARE};

class Shape {
public:
    ShapeType type;
    virtual double distance(Shape& otherShape) = 0;
};

class Circle : public Shape {
public:
    ShapeType type = CIRCLE;
    double distance(Shape& otherShape) override;
};


double circleCircleDistance(Circle& circle1, Circle& cirlce2){
    return 0; //pretend this does the calculation
};

double Circle::distance(Shape &otherShape) {
    switch (otherShape.type){
        case CIRCLE:
            //Here I get the error
            //cannot bind base class object of type Shape to derived class reference Circle& for 2nd argument
            return circleCircleDistance(*this, otherShape);
            
    }
}

Solution

  • You would have to cast the Shape& to a Circle&

    return circleCircleDistance(*this, static_cast<Circle&>(otherShape));
    

    As an aside, I'd handle your types a bit differently

    class Shape {
    public:
        virtual ShapeType get_type() const = 0;  // derived classes must override this
        virtual double distance(Shape& otherShape) = 0;
    };
    
    class Circle : public Shape {
    public:
        ShapeType get_type() const override { return CIRCLE; } // here's your override
        double distance(Shape& otherShape) override;
    };
    
    ...
    {
       switch (otherShape.get_type()){
    

    Otherwise you're going to get into a situation where type is shadowed from the derived/base classes depending how you access it.