I am new to C and I am currently playing with inheritance. I am creating a base Polygon class that is inherited by Rectangle and Triangle classes respectively. From there I want to print out the area as defined in calcArea
. However, the output of my derived class instances seem to be null.
From what I understand the Polygon:(name, width, height)
can help to initialize variables that already exist in the base class. Thanks for all the help!
Here's my code:
#include <iostream>
#include <string>
using namespace std;
enum Polytype {POLY_PLAIN, POLY_RECT, POLY_TRIANG};
class Polygon
{
public:
Polygon(string name, double width, double height){
_name = name;
_width = width;
_height = height;
_polytype = POLY_PLAIN;
}
virtual ~Polygon()
{
cout << "Destroying polygon" << endl;
}
virtual Polytype getPolytype(){
return _polytype;
}
virtual void setPolytype(Polytype polytype){
_polytype = polytype;
}
virtual string getName(){
return _name;
}
virtual double calcArea(){
return _width * _height;
}
private:
string _name;
double _width;
double _height;
Polytype _polytype;
};
class Rectangle: public Polygon
{
public:
Rectangle(string name, double width, double height) : Polygon(name, width, height){
_polytype = POLY_RECT;
};
~Rectangle()
{
cout << "Destroying rectangle" << endl;
}
Polytype getPolytype(){
return _polytype;
}
void setPolytype(Polytype polytype){
_polytype = polytype;
}
double calcArea(){
return _width * _height;
}
string getName(){
return _name;
}
private:
string _name;
double _width;
double _height;
Polytype _polytype = POLY_RECT;
};
class Triangle: public Polygon
{
public:
Triangle(string name, double width, double height) : Polygon(name, width, height){
_polytype = POLY_TRIANG;
};
~Triangle()
{
cout << "Destroying triangle" << endl;
}
Polytype getPolytype(){
return _polytype;
}
void setPolytype(Polytype polytype){
_polytype = polytype;
}
string getName(){
return _name;
}
double calcArea(){
return 0.5 * _width * _height;
}
private:
string _name;
double _width;
double _height;
Polytype _polytype;
};
int main(){
//Initialize rectangle and triangle and store them onto the stack
Rectangle rect("RectA", 10.0, 20.0);
Triangle triang("TriangB", 10.0, 20.0);
cout << "Name is " << rect.getName() << endl;
cout << "Name is "<< triang.getName() << endl;
string rectArea = to_string(rect.calcArea());
string triangArea = to_string(triang.calcArea());
cout << "RectA's area is " << rectArea << endl;
cout << "TriangB's area is " << triangArea << endl;
return 0;
}
And here's my output:
Name is
Name is
RectA's area is 0.000000
TriangB's area is 0.000000
Destroying triangle
Destroying polygon
Destroying rectangle
Destroying polygon
CodePudding user response:
The main problem is that you have variables in the sub classes shadowing the names in the base class - so you assign values to the variables in the base class, but you later print the values of the default initialized variables in the sub classes.
You actually mostly need to remove code.
I would rethink the name of the base class though. Polygon
is not a good name for a class with only width and height. I'll leave that up to you.
I've replaced all endl
with \n
. They do the same thing, but endl
flushes the output, which is usually not needed - but it is usually also expensive.
Example:
#include <iostream>
#include <string>
enum Polytype { POLY_PLAIN, POLY_RECT, POLY_TRIANG };
class Polygon {
public:
Polygon(std::string name, double width, double height)
: Polygon(name, width, height, POLY_PLAIN) {}
virtual ~Polygon() { std::cout << "Destroying polygon\n"; }
// make member functions that does not change the object `const`:
virtual Polytype getPolytype() const { return _polytype; }
virtual void setPolytype(Polytype polytype) { _polytype = polytype; }
virtual const std::string& getName() const { return _name; }
// in your case, the implementation could actually be in the base class - but
// I've made it into a pure virtual here.
virtual double calcArea() const = 0; // no instances can be made of Polygon
protected:
// only derived classes can access this constructor:
Polygon(std::string name, double width, double height, Polytype ptype)
: _name(name), _width(width), _height(height), _polytype(ptype) {}
std::string _name;
double _width;
double _height;
Polytype _polytype;
};
class Rectangle : public Polygon {
public:
Rectangle(std::string name, double width, double height)
//use the protected base class ctor:
: Polygon(name, width, height, POLY_RECT) {};
~Rectangle() { std::cout << "Destroying rectangle\n"; }
// the only implementation needed in this sub class:
double calcArea() const override { return _width * _height; }
};
class Triangle : public Polygon {
public:
Triangle(std::string name, double width, double height)
: Polygon(name, width, height, POLY_TRIANG) {};
~Triangle() { std::cout << "Destroying triangle\n"; }
// the only implementation needed in this sub class:
double calcArea() const override { return 0.5 * _width * _height; }
};
int main() {
// Initialize rectangle and triangle and store them onto the stack
Rectangle rect("RectA", 10.0, 20.0);
Triangle triang("TriangB", 10.0, 20.0);
std::cout << "Name is " << rect.getName() << '\n';
std::cout << "Name is " << triang.getName() << '\n';
std::cout << "RectA's area is " << rect.calcArea() << '\n';
std::cout << "TriangB's area is " << triang.calcArea() << '\n';
}
CodePudding user response:
I realized that I did not have to redeclare the private variables in my subclasses. That is probably the reason why it returned null.
#include <iostream>
#include <string>
using namespace std;
enum Polytype {POLY_PLAIN, POLY_RECT, POLY_TRIANG};
class Polygon
{
public:
Polygon(string name, double width, double height){
_name = name;
_width = width;
_height = height;
_polytype = POLY_PLAIN;
}
~Polygon()
{
cout << "Destroying polygon" << endl;
}
virtual Polytype getPolytype(){
return _polytype;
}
virtual void setPolytype(Polytype polytype){
_polytype = polytype;
}
virtual string getName(){
return _name;
}
virtual double calcArea(){
return _width * _height;
}
protected:
string _name;
double _width;
double _height;
Polytype _polytype;
};
class Rectangle: public Polygon
{
public:
Rectangle(string name, double width, double height) : Polygon(name, width, height){
_polytype = POLY_RECT;
};
~Rectangle()
{
cout << "Destroying rectangle" << endl;
}
Polytype getPolytype(){
return _polytype;
}
void setPolytype(Polytype polytype){
_polytype = polytype;
}
double calcArea(){
return _width * _height;
}
string getName(){
return _name;
}
};
class Triangle: public Polygon
{
public:
Triangle(string name, double width, double height) : Polygon(name, width, height){
_polytype = POLY_TRIANG;
};
~Triangle()
{
cout << "Destroying triangle" << endl;
}
Polytype getPolytype(){
return _polytype;
}
void setPolytype(Polytype polytype){
_polytype = polytype;
}
string getName(){
return _name;
}
double calcArea(){
return 0.5 * _width * _height;
}
};
int main(){
//Initialize rectangle and triangle and store them onto the stack
Rectangle rect("RectA", 10.0, 20.0);
Triangle triang("TriangB", 10.0, 20.0);
cout << "Name is " << rect.getName() << endl;
cout << "Name is "<< triang.getName() << endl;
string rectArea = to_string(rect.calcArea());
string triangArea = to_string(triang.calcArea());
cout << "RectA's area is " << rectArea << endl;
cout << "TriangB's area is " << triangArea << endl;
return 0;
}