Reputation: 69
The thing is that I am struggling with making objects of the class Shape. I declare the vector, but then do not know how to connect it to the class Shape and its objects. The code itself has one base class, which is Shape and then two subclasses Circle and Rectancle. The idea of the code is to use a vector in the main function, and have multiple cases for the Circle area and the Rectangle area. This is the code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Shape
{
public:
virtual double GetArea() const = 0
{
}
private:
};
class Circle : public Shape
{
public:
Circle(double p, double r) // constructor
{
pi = p;
radius = r;
}
Circle() : pi(3.14), radius(0) {} // default constructor
void SetRadius(double value)
{
radius = value;
}
double GetRadius() const
{
return radius;
}
double GetArea()
{
double area = pi * radius * radius;
return area;
}
private:
double pi = 3.14;
double radius;
};
class Rectangle : public Shape
{
public:
Rectangle(double a, double b) // constructor
{
sideA = a;
sideB = b;
}
Rectangle() : sideA(0), sideB(0) {} // default constructor
void SetSideA(double value)
{
sideA = value;
}
double getSideA() const
{
return sideA;
}
void SetSideB(double val)
{
sideB = val;
}
double getSideB() const
{
return sideB;
}
double getArea()
{
double Area = sideA * sideB;
return Area;
}
private:
double sideA;
double sideB;
};
int main()
{
vector<Shape*> shape;
return 0;
}
Upvotes: 4
Views: 374
Reputation: 73384
You want Polymorphism. You just use the constructor of the circle or the rectangle, for example:
vector<Shape*> shape(1);
if(/* case is circle*/)
shape[0] = new Circle();
else
shape[0] = new Rectangle();
However, you need remove the definition of the pure virtual method in the base class, since it's inside the class, and only declare it.
Then, you need to implement that method, by using exactly the same prototype, so you need to mark the method in Circle as const
too. Same for Rectangle class, where you also did a typo, since the name of the method is "GetArea", not "getArea".
Complete Minimal Working Example:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Shape
{
public:
virtual double GetArea() const = 0;
virtual ~Shape() {};
};
class Circle : public Shape
{
public:
Circle(double p, double r) // constructor
{
pi = p;
radius = r;
}
Circle() : pi(3.14), radius(0) {} // default constructor
void SetRadius(double value)
{
radius = value;
}
double GetRadius() const
{
return radius;
}
double GetArea() const
{
double area = pi * radius * radius;
return area;
}
private:
double pi = 3.14;
double radius;
};
class Rectangle : public Shape
{
public:
Rectangle(double a, double b) // constructor
{
sideA = a;
sideB = b;
}
Rectangle() : sideA(0), sideB(0) {} // default constructor
void SetSideA(double value)
{
sideA = value;
}
double getSideA() const
{
return sideA;
}
void SetSideB(double val)
{
sideB = val;
}
double getSideB() const
{
return sideB;
}
double GetArea() const
{
double Area = sideA * sideB;
return Area;
}
private:
double sideA;
double sideB;
};
int main()
{
vector<Shape*> shape(2);
shape[0] = new Circle(3.14, 1);
shape[1] = new Rectangle(2, 3);
for(auto s : shape)
std::cout << "Shape area = " << s->GetArea() << endl;
// When you are done, delete the dynamically allocated memory.
// You can use smart pointers in order to avoid doing this manually (and maybe forget!)
delete shape[0];
delete shape[1];
return 0;
}
Output:
Shape area = 3.14 Shape area = 6
where the first area is from the circle, and the second area from the rectangle.
I suggest you read: Virtual destructor in polymorphic classes and What is the 'override' keyword in C++ used for?
After doing all this for practice, you should really start using smart pointers, like this for instance std::vector<std::unique_ptr<Shape>> shape;
, instead of raw pointers. This way, you won't have to worry about deleting manually dynamically allocated memory.
Upvotes: 8
Reputation: 311048
For starters the class Shape must have a virtual destructor
class Shape
{
public:
virtual double GetArea() const = 0
{
}
virtual ~Shape() = default;
};
Within the class the member function GetArea
is declared with the qualifier const. So in derived classes the overriding function shall also have the qualifier const.
double GetArea() const override
{
double area = pi * radius * radius;
return area;
}
and
double getArea() const override
{
double Area = sideA * sideB;
return Area;
}
In main you can use the member function push_back to append pointers to objects, For example
std::vector<Shape*> shape;
Shape *p = new Circle( 3.14, 10.0 );
shape.push_back( p );
p = new Rectangle( 10.0, 20.0 );
shape.push_back( p );
Instead of the vector of the type
std::vector<Shape *> shape;
you could use a vector of std::unique_ptr<Shape>
. For example
std::vector<std::unique_ptr<SHape>> shape;
In this case you will not need to delete the pointers manually for example by using the standard algorithm std::for_each
for the vector.
Upvotes: 3