0

I need to be able to use a base pointer to hold the address of either a rectangle or a circle. Which one would be determined at run time. I then want to use the pointers to call different virtual functions depending on which type they are. I can get this concept to work if the functions only use one Shape pointer. However many of my functions require two objects to work.

If I use a pure virtual functions, both Rectangle and Circle classes become abstract and I can not use the objects (error C2259). If I declare the functions as I did down below, all of the calls go to the Base class Shape. Any help is greatly appreciated.

class Shape {
public:
    virtual double overlappingArea(const Shape&)const {return 0;};
    //replacing with a pure virtual function causes the other classes to become abstract
    //virtual double overlappingArea(const Shape&)const = 0;
    //This returns error C2259 (or pure virtual function has no overload)
    //I know this is because the program has no overloads with identical parameters

};

class Rectangle : virtual public Shape {
public:
    Rectangle(int X, int Y, int L, int W) : x(X), y(Y), l(L), w(W) {}

    double overlappingArea(const Rectangle& R)const {
        double area = 1.1;
        //code that finds the overlapping area
        return area;
    }

    double overlappingArea(const Circle& C)const {
        double area = 1.2;
        //code that finds the overlapping area
        return area;
    }
private:
    int x, y, l, w;
};

class Circle: virtual public Shape {
public:
    Circle(int X, int Y, int R) : x(X), y(Y), r(R) {}

    double overlappingArea(const Rectangle& R)const {
        double area = 2.1;
        //code that finds the overlapping area
        return area;
    }

    double overlappingArea(const Circle& C)const {
        double area = 2.2;
        //code that finds the overlapping area
        return area;
    }
private:
    int x, y, r;
};

int main() {
    Shape* F1 = new Rectangle(0,0,1,1);
    Shape* F2 = new Rectangle(1,1,2,2);
    Shape* C1 = new Circle(0,0,1);
    Shape* C2 = new Circle(1,1,2);

    double areaFF, areaFC, areaCC;

    areaFF = F1->overlappingArea(*F2);
    areaFC = F1->overlappingArea(*C1);
    areaCC = C1->overlappingArea(*C2);    

    return 0;
}

All the areas end up equaling 0. I want areaFF = 1.1 , areaFC = 1.2 , areaCC = 2.2

Thanks for the help
Working code if you're interested

#include <iostream>
using namespace std;

class Rectangle;
class Circle;

class Shape {
public:
    virtual double overlapwith(const Shape&)const = 0;
    virtual double overlap(const Rectangle&)const = 0;
    virtual double overlap(const Circle&)const = 0;

};


class Circle : public Shape {
public:
    Circle() : x(0), y(0), r(0) {
    }
    Circle(int X, int Y, int R) : x(X), y(Y), r(R) {
    }

    double overlapwith(const Shape &with)const {
        cout << "\nCirc::overlapwith(const Shap&)const";
        return with.overlap(*this);
    }
    double overlap(const Rectangle &w)const {
        cout << "\nCirc::overlap(const Rect&)const";
        return 12;
    }
    double overlap(const Circle &w)const {
        cout << "\nCirc::overlap(const Circ&)const";
        return 11;
    }

private:
    int x, y, r;

};

class Rectangle : public Shape {
public:
    Rectangle() : x(0), y(0), l(0), w(0) {
    }
    Rectangle(int X, int Y, int L, int W) : x(X), y(Y), l(L), w(W) {
    }

    double overlapwith(const Shape &with)const {
        cout << "\nRect::overlapwith(const Shap&)const";
        return with.overlap(*this);
    }
    double overlap(const Rectangle &w)const {
        cout << "\nRect::overlap(const Rect&)const";
        return 22;
    }
    double overlap(const Circle &w)const {
        cout << "\nRect::overlap(const Circ&)const";
        return 21;
    }

private:
    int x, y, l, w;

};





int main() {

    Shape* F1 = new Rectangle(0,0,1,1);
    Shape* F2 = new Rectangle(1,1,2,2);
    Shape* C1 = new Circle(0,0,1);
    Shape* C2 = new Circle(1,1,2);


    double ff, fc, cf, cc;
    ff = F1->overlapwith(*F2);
    fc = F1->overlapwith(*C2);
    cf = C1->overlapwith(*F2);
    cc = C1->overlapwith(*C2);

    cout << "\n\n\tff : " << ff
        << "\n\tfc : " << fc
        << "\n\tcf : " << cf
        << "\n\tcc : " << cc;

    int pb; cin >> pb;
    return 0;
}
3
  • 1
    Start by removing class-name qualification inside the class (eg. Circle::), and look up the keyword 'override', if you're using C++11. Commented Dec 5, 2016 at 3:04
  • Sorry about the Rectangle:: . I copied some of the code from a program where each class had a separate .h and .cpp file Commented Dec 5, 2016 at 3:10
  • 2
    ah, the infamous double dispacth problem Commented Dec 5, 2016 at 3:28

1 Answer 1

1

Define two more pure virtual methods in the base class, in addition to the existing virtual methods, which can be pure. You will need to do some simple forward declarations:

class Rectangle;
class Circle;

class Shape {
public:
    virtual double overlappingArea(const Shape&) const=0;
    virtual double overlappingAreaWith(const Rectangle&) const=0;
    virtual double overlappingAreaWith(const Circle&) const=0;
};

In each subclass, implement the first virtual method (the existing one) by invoking overlappingAreaWith() for the passed Shape & parameter, passing *this as the parameter:

class Rectangle {

    // ...

    double overlappingArea(const Shape &with) const override
    {
        return with.overlappingAreaWith(*this);
    }
};

class Circle {

    // ...

    double overlappingArea(const Shape &with) const override
    {
        return with.overlappingAreaWith(*this);
    }
};

Now, implement the other two overlappingAreaWith() methods in both Circle and Rectangle subclasses. They will now receive the other object, as either a Circle or a Rectangle parameter, as the case may be.

Each subclass is correctly implementing all three pure virtual methods.

Sign up to request clarification or add additional context in comments.

1 Comment

For the record, this is the Visitor pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.