'Copy child object to parent object

I have three classes: Shape, Rectangle and Circle. Shape is parent of two other class. definition of this classes is in following code:

#include <iostream>

using namespace std;

class Shape {
public:
    Shape() {

    }

    ~Shape() {

    }

    void set(float BORDER, string COLOR) {
        border = BORDER;
        color = COLOR;
    }

    double computeArea() {
        return 0;
    }

private:
    float border;
    string color;
};

class Circle : public Shape {
public:
    Circle() {

    }

    ~Circle() {

    }

    void setRadius(float RADIUS) {
        radius = RADIUS;
    }

    double computeArea() {
        return 3.14 * radius * radius;
    }

private:
    float radius;
};


class Rectangle : public Shape {
public:
    Rectangle() {

    }

    ~Rectangle() {

    }

    void setWidth(float w) {
        width = w;
    }

    void setLength(float l) {
        length = l;
    }

    double computeArea() {
        return width * length;
    }

private:
    float width;
    float length;
};

I build two object from Circle and Rectangle classes. Then I copied this two object into Shape class. When I run computeArea() function in following order I get 0 result.

#include <iostream>

using namespace std;

int main() {
    Circle c;
    c.setRadius(3);
    Rectangle r;
    r.setWidth(4);
    r.setLength(5);

    Shape sh[2];

    sh[0] = c;
    sh[1] = r;

    cout << sh[0].computeArea() << endl;
    cout << sh[1].computeArea();

    return 0;
}

I want compute area of all shapes with correct function. How can I do that?

Thanks in Advance



Solution 1:[1]

To expand on what Fureeish said, change your code to this:

int main() {
    Circle c;
    c.setRadius(3);
    Rectangle r;
    r.setWidth(4);
    r.setLength(5);

    Shape *sh[2];

    sh[0] = &c;
    sh[1] = &r;

    cout << sh[0]->computeArea() << endl;
    cout << sh[1]->computeArea();

    return 0;
}

and declare computeArea (and also Shape's destructor, in case you destroy a derived object through a pointer to the base class) as virtual.

Assigning a derived class to an object of the base class is known as 'object slicing' and usually leads to undesirable results. Using pointers (or references) avoids this.

Solution 2:[2]

In Shape class make computeArea() an abstract(or purely virtual) method:

virtual double computeArea() =0;

Solution 3:[3]

You seem to be missing the virtual keyword.

The destructor of the base class Shape needs to be virtual as well (in case you ever decide to manipulate any of the derived objects through a pointer to the base class).

The function computeArea() must be declared virtual, like this virtual double computeArea() { ... }.

#include <iostream>

using namespace std;

class Shape {
public:
    Shape() {

    }

    virtual ~Shape() {

    }

    void set(float BORDER, string COLOR) {
        border = BORDER;
        color = COLOR;
    }

    virtual double computeArea() {
        return 0;
    }

private:
    float border;
    string color;
};

class Circle : public Shape {
public:
    Circle() {

    }

    virtual ~Circle() {

    }

    void setRadius(float RADIUS) {
        radius = RADIUS;
    }

    virtual double computeArea() {
        return 3.14 * radius * radius;
    }

private:
    float radius;
};


class Rectangle : public Shape {
public:
    Rectangle() {

    }

    virtual ~Rectangle() {

    }

    void setWidth(float w) {
        width = w;
    }

    void setLength(float l) {
        length = l;
    }

    virtual double computeArea() {
        return width * length;
    }

private:
    float width;
    float length;
};

Also if you are using C++11 or newer, you can add the overrride keyword at endd of the computeArea function definitions, like this

    virtual double computeArea() override {
        return width * length;
    }

and this,

    virtual double computeArea() override {
        return 3.14 * radius * radius;
    }

in the respective classes.

And then modify the main function like this.

    int main() {
    Circle c;
    c.setRadius(3);
    Rectangle r;
    r.setWidth(4);
    r.setLength(5);

    Shape *sh1, *sh2;

    sh1 = &c;
    sh2 = &r;

    cout << sh1->computeArea() << endl;
    cout << sh2->computeArea();

    return 0;
}

EDIT: Also, as others have pointed out, you need pointers to the base class and don't need to copy your derived class objects to the base class object. See the modified main() function please.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Salma Halloumi
Solution 3