Nicholaus Cjj
Nicholaus Cjj

Reputation: 33

Accessing the grand child of a class using polymorphism in C++

I was asked to implement this chart in polymorphism, which the output is to calculate geometry:

The criteria is as follows:

Here's the snippet of what I've done. To shorten, I'll put 2d class as an example:

//base initiation
    class Shape{
public: 
    virtual void print(){};
    virtual void getArea(double n){};
};

//2d class which is derived from base class
class TwoDimensionalShape : public Shape{
public:
    virtual void getPerimeter(double n){};
};

//The actual shape
class Circle : public TwoDimensionalShape{
protected: 
    double perimeter, area;
public:
    void getArea(double radius){
         this->area=(3.1415*radius*radius);
    }
    void getPerimeter(double radius){
        this->perimeter=(3.1415*2*radius);
    }
    void print(){
        cout << "Circle's perimeter: " << this->perimeter << endl;
        cout << "Circle's area: " << this->area << endl;
    }
    Circle(){};
    ~Circle(){};
};

And for the usage itself is:

//setting the object as global
Shape *object;
//the class
void circle(){
    Circle circle;
    object=&circle;
    double radius;
    system("cls");
    do{
        cout << "Enter radius value: ";
        cin >> radius; flush();
    } while (radius<=0);
    object->getPerimeter(radius); object->getArea(radius);
    object->print(); cin.get();
}

And I think I did it okay, but not! The error list shows:

Error   4   error C2039: 'getPerimeter' : is not a member of 'Shape'
Error   5   IntelliSense: class "Shape" has no member "getPerimeter"    

I was thinking about using cast, but I plainly have no experience with it.

Long story short, how do I able to access any kind of derived class only by using Shape *object (This object is also used for sphere, cube, tetrahedron, etc)?

p.s. this is not a duplicate of What should the TwoDimensionalShape Class contain? as it asks a totally different thing

EDIT 1: Yeah the signatures suck so I will edit my code in my desktop later as well as this one so please continue. Thanks!

Upvotes: 3

Views: 1073

Answers (4)

jbalestr42
jbalestr42

Reputation: 74

First of all if your base class is abstract your methods should looks like this :

class Shape {
public: 
    virtual void print() = 0;
    virtual double getArea() = 0;
};

Then the childs class can have there own pure virtual method

getVolume or getPerimeter

class TwoDimensionalShape : public Shape{
public:
    virtual double getArea() { return getPerimeter(); }
    virtual double getPerimeter() = 0;
};

And Circle can now implements the method getPerimeter and use it's own value to compute the perimeter

class Circle : TwoDimensionalShape {
private:
    float m_radius;

public: 
    virtual double getPerimeter() { return 2.0 * PI * m_radius; }
};

Upvotes: 0

AresCaelum
AresCaelum

Reputation: 1566

So let me pick apart what you have said:

print() and getArea() function are placed in base class, which is Shape. It is also asked that it's a pure virtual function but I'm starting to doubt it(..?)

From your code you don't know what a pure virtual is, any class with a pure virtual becomes whats called an abstract base class, a keynote about an abstract base class is that you cannot create an instance of it and every class that inherits from it has to overwrite these functions, you make a pure virtual function by doing the following:

class Shape{
public: 
    virtual void print() = 0;
    virtual double getArea() = 0;
};

getPerimeter() function is placed in 2d class, and getArea() is placed in 3d class

getArea() and getPerimeter() are you sure its not suppose to be getVolume() and getPerimeter(), as those would make sense to be in the children classes, based on your third requirement. getArea() would already exist in the 3d class as the 3d class has to overwrite it and so does the 2d class.

Long story short, how do I able to access any kind of derived class only by using Shape *object (This object is also used for sphere, cube, tetrahedron, etc)?

Simply put, you don't as your Shape* will have no idea as to what getPerimeter() is or what getVolume() as they were not defined in the base class. You do have the option of using a temporary TwoDimensionalShape* and dynamically casting object to that, and then using that temporary pointer to get the perimeter.

Like:

TwoDimensionalShape* ptr_shape = dynamic_cast<TwoDimensionShape*>(object);
if(ptr_shape)
{
    ptr_shape->getPerimeter(/*arguments here if you have them...*/)
}

Upvotes: 1

Cyril LOUISIN
Cyril LOUISIN

Reputation: 1

You need do a safe down cast, use dynamic_cast.

TwoDimensionalShape* shape_eddge = dynamic_cast<TwoDimensionalShape*>(circle);
if (shape_eddge)
  shape_eddge->getPerimeter()

http://en.cppreference.com/w/cpp/language/dynamic_cast

Upvotes: 0

Bartek Banachewicz
Bartek Banachewicz

Reputation: 39370

how do I able to access any kind of derived class only by using Shape *object

You can't. If you know that something is a two-dimensional shape, you should access it via such interface (doesn't really matter whether you upcast &circle into a 2D shape pointer or downcast the Shape pointer, in this particular example at least). The base Shape class doesn't have getPerimeter function and correctly won't allow you to use it.

Upvotes: 2

Related Questions