Reputation: 33
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
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
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
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
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