C++ Geometry hierarchy, Class upcasting and inheritance - c++

I am working on a project for understanding classes and have hit a wall. If you have any advice about my syntax, please let me know where I am going wrong as I am still quite new to programming, but my question is to do with class inheritance. (A, C and D are included but pretty well completed).
My project:
A. Start with a point class... Override << (print values), +, - (to add and subtract point coordinates). I feel I have completed this portion.
B. Create a base class Shape. Shape will contain functions to calculate area, circumference and take point values to create a box that encapsulates the given shape. These will be overloaded by derived classes. Create a display() function that displays all relevant info (name, area, circumference and encapsulating box.
C. Build a heirarchy for shapes by making circle, square, triangle... add default and custom constructors whos arguments initialize the shapes using the correct number of point objects. I feel I have satisfied this too.
D. In main() Create an instance of each. Circle radius = to 23, square sides each = 25, Triangle sides = 10, 20 and 30 (very flat triangle, area = 0). Define each to contain the origin (0, 0). Display all the info. I feel I have completed this (minus the display function).
My question is (and where I am struggling), "How do I properly make/access functions from a base class (shape) to return meaningful information."
Do I literally just make them all virtual since some classes dont have the same information as others? (like Area() and Circumference()?)
#include <iostream>
#include <cmath>
using namespace std;
class Point {
public:
int x, y;
Point() {
x = 0;
y = 0;
}
Point(int x, int y): x(x), y(y) {} // constructor
friend ostream& operator<<(ostream& out, const Point number) { //Involves ostream to output the numbers
out << "(" << number.x << ", " << number.y << ")"; //that were input into the x and y values of Point.
return out;
}
friend Point operator+(Point first, Point second) { //Takes two mathematical vectors and tells the compiler
Point add; // to add the x values together and the y values together
add.x = first.x + second.x;
add.y = first.y + second.y;
return add;
}
friend Point operator-(Point first, Point second) { // same as above but with subtraction.
Point subtract;
subtract.x = first.x - second.x;
subtract.y = first.y - second.y;
return subtract;
}
};
class Shape {
protected:
float height, width;
public:
Shape() {
height = 0;
width = 0;
}
Shape(float h, float w) {
height = h;
width = w;
}
/*
int Display() {
//Do something..... Create a display function
return 0;
}
int BoundingBox() {
//Do something again......
return 0;
}
*/
virtual float Area() const = 0;
virtual float Circumference() const = 0;
virtual ~Shape() {};
};
class Circle: public Shape {
Point center;
float radius;
public:
Circle(): Shape() {};
Circle (Point p1, float r) { //Takes center point object, and given radius.
center = p1;
radius = r;
}
virtual float Area() const override { // Calculates circle area
return(M_PI * radius * radius);
}
virtual float Circumference() const override { // Calculates circumference
return(float (M_PI * 2 * radius));
}
virtual ~Circle() {};
};
class Square: public Shape {
Point first, second, third, fourth;
public:
Square(): Shape() {};
Square(Point p1, Point p2, Point p3, Point p4) { // Takes four point arguments and initializes them
first = p1;
second = p2;
third = p3;
fourth = p4;
height = second.x - first.x; //calculates the height and width from points
width = third.y - first.y;
}
virtual float Circumference() const override {
return 0; //Errors without the return statement
}
virtual float Area() const override{ // Calculates area by measuring the difference between given points
return(height * width);
}
virtual ~Square() {};
};
class Triangle: public Shape {
Point first, second, third;
public:
Triangle(): Shape() {};
Triangle(Point p1, Point p2, Point p3) { // Takes three point arguments and initializes them
first = p1;
second = p2;
third = p3;
height = third.y - first.y;// due to the nature of the question, this only works for flat triangles.
width = second.x - first.x;
}
virtual float Circumference() const override {
return 0; //Errors without the return statement
}
virtual float Area() const override {
return ((height * width) / 2);
}
virtual ~Triangle() {};
};
int main() {
Point p1(0, 0), p2(25, 0), p3(0, 25), p4(25, 25), p5(20, 0), p6(30, 0);
Circle c1 (p1, 23); // Circle with origin (0, 0) and a radius of 23
Square s1 (p1, p2, p3, p4); // Square with 4 points and the origin
Triangle t1 (p1, p5, p6); // Extraordinarily flat triangle with origin
cout << c1.Circumference() << endl;
cout << s1.Area() << endl;
cout << t1.Area() << endl;
}
At this point, I am feeling a bit lost of the woods and I am sure I have either created several mistakes along the way, or just a few, but regardless, I don't understand. Any advice would be appreciated!
edit: I have updated my code to include the recommendations to include virtual deconstructors, remove the getheight etc... statements, and add virtual to the derived functions

When you're working with inheritance, make sure to use a virtual destructor in all of your inherited classes, as well as the base class.
Your inherited virtual functions would benefit from being marked virtual and override too, in case you want to make further specializations.
You are overriding inherited functions, but then they do the same thing as the original, e.g. GetHeight(). That kinda defeats the point of inheriting those functions. They also do not need to be virtual if they aren't overridden.
Your derived classes would benefit from explicitly calling the base class's constructor. It will call the default constructor if you don't provide a specific constructor to call, which may or may not be the behaviour you intended - IMO it's safer to always provide the base class constructor you want!
As an example:
class Shape {
protected:
float height, width;
public:
Shape() {
height = 0;
width = 0;
}
Shape(float h, float w) {
height = h;
width = w;
}
virtual float Area() const = 0;
virtual float Circumference() const = 0;
virtual ~Shape() {};
};
class Circle: public Shape {
Point center;
float radius;
public:
Circle() : Shape() {};
Circle (Point p1, float r) : Shape() {
// Note you may wish to set the height and width here!
//Takes center point object, and given radius.
center = p1;
radius = r;
}
virtual float Area() const override { // Calculates circle area
return(M_PI * radius * radius);
}
virtual float Circumference() const override { // Calculates circumference
return(float (M_PI * 2 * radius));
}
virtual ~Circle() {};
};

Related

Why it keeps return 0 when I enter the Data of The Heigh & Base

class BASIC_SHAPE (abstract)
class BASIC_SHAPE
{
public:
double GET_AREA(double _AREA) { AREA = _AREA; return AREA; }
virtual double CALC_AREA() = 0;
private:
double AREA =0;
};
Class CIRCLE
class CIRCLE:public BASIC_SHAPE
{
public:
CIRCLE() { RADIUS = 0; }
CIRCLE(double _RADIUS) { RADIUS = _RADIUS; }
virtual double CALC_AREA() {
double TEMP2 = 3.14 * pow(RADIUS, 2);
return GET_AREA(TEMP2);
}
private:
double RADIUS;
};
Class TRIANGLE
class TRIANGLE: BASIC_SHAPE
{
public:
TRIANGLE() { BASE = 0; HEIGHT = 0; }
TRIANGLE(double _BASE , double _HEIGHT) : BASE{_BASE}, HEIGHT{_HEIGHT} {}
virtual double CALC_AREA() {
double TEMP = 1 / 2 * (BASE * HEIGHT);
return GET_AREA(TEMP);
}
private:
double BASE, HEIGHT;
MAIN
CIRCLE SHAPE2;
TRIANGLE SHAPE3;
void main()
{
double RAD;
std::cout << "Enter a Circle Radius : ";
std::cin >> RAD;
CIRCLE SHAPE2(RAD);
CIRCLE* LEAD1 = new CIRCLE(RAD);
std::cout << "The Area is : " << LEAD1->CALC_AREA();
double BASE , HEIGHT;
std::cout << "\n\nEnter a Triangle Base : ";
std::cin >> BASE;
std::cout << "\nEnter a Triangle Height : ";
std::cin >> HEIGHT;
TRIANGLE SHAPE3(BASE, HEIGHT);
std::cout << SHAPE3.CALC_AREA();
}
it keeps returning zero when I input the BASE & HEIGHT
I have tried using arrow operator and get it with pointers put nothing worked , I,ve tried use pointers and other methods to give me the answer or the SUM of area but nothing happens . constructors or abstract Class are suspected but IDK how ??
As pointed out in the comments by #rturrado 1/2 is 0. 0 times anything is 0. either use 0.5 or 1/2.0*....
Also, why does your GET_AREA method set the area for the base class and return the set area? You need to have different getters and setters. Getter methods should not set and similarly setter methods should not get.
Also, it would be best if you get in the habit of using managed pointers.

How to write a template function that adds an object of variant class type to a vector?

I have another problem that I have no idea how to solve. Maybe somebody can help me.
What I want to do:
I have a vector that shall take elements of various class types. In my example code I have two classes (Line, circle) that are both derived from a virtual class segment.
My code shall chain several circle or Line elements and put them in the vector. Each element may be different from the other (different radii, different starting and ending points, etc) and the sequence of elements shall vary from execution to execution. That is for instance for the first execution I have a circle with radius 2 followed by another circle of radius 1, followed by a Line of length 4 and for the second execution I have a Line of length 1 followed by another Line of Length 5 in a different direction, followed by a circle of radius 0.5.
I've already learned how to compose the vector such that it can contain different types but as of now the sequence and definition of each element is hard-coded. Now I want to make this flexible (in the end the sequence and definition shall be file-driven). For this I attempt to implement a template function that takes whatever element is fed into it and adds it to the vector. The current definition also takes the vector as input but I may end up to define this function as a method for the vector.
Unfortunately I cannot figure out a way how to do it that works. I understand that I cannot copy a unique_ptr so I tried with the std::move() method but doesn't work. I get an C2664 error message of the xmemory module in line 671 saying that I cannot convert argument 1 in T2 into a std::nullptr_t.
Can somebody help me here? That'll be so awesome!
Here's my example code that implements the basic idea for my code:
#include <iostream>
#include <vector>
#include <variant>
struct point
{
double x;
double y;
};
class segment
{
public:
segment()
{
P1.x = 0;
P1.y = 0;
P2.x = 0;
P2.y = 0;
};
virtual ~segment() {};
virtual double get_radius() { return 0; };
virtual double get_length() { return 0; };
virtual double get_angle() { return 0; };
int segment_id = 0;
protected:
point P1;
point P2;
};
class Line : public segment
{
public:
Line() {};
Line(const point pt1, const point pt2)
{
P1.x = pt1.x;
P1.y = pt1.y;
P2.x = pt2.x;
P2.y = pt2.y;
segment_id = 1;
};
~Line() {};
double get_length() { return calc_length(); };
double get_angle() { return calc_angle(); };
private:
double calc_length()
{
// calculate length (here: dummy value)
return 1;
}
double calc_angle()
{
// calculate angle (here: dummy value)
return 0.5;
}
double length = 0;
double angle = 0;
}
;
class circle : public segment
{
public:
circle()
{
center.x = 0;
center.y = 0;
};
circle(const double r, const point c)
{
radius = r;
center.x = c.x;
center.y = c.y;
segment_id = 2;
};
~circle() {};
double get_radius() { return radius; };
point get_center() { return center; };
double get_length() { return 3.14 * radius; }; //returns circumference
private:
double radius = 0;
point center;
};
//-------------------------------------------------------
//T1: class type "segment", T2: class object Line or circle
template<typename T1, typename T2>
inline void add_segment(T1 v, T2 line_or_circle)
{
v.emplace_back(line_or_circle);
}
//-------------------------------------------------------
int main()
{
int nbr = 5;
point start;
start.x = 1;
start.y = 2;
point end;
end.x = 3;
end.y = 4;
point c;
c.x = 0;
c.y = 0;
double r = 9;
auto anotherCircle = std::make_unique<circle>(r, c);
auto anotherLine = std::make_unique<Line>(start, end);
circle myCircle(r, c);
//VERSION 1: Does now compile.
std::vector<std::unique_ptr<segment>> v1;
v1.emplace_back(std::move(anotherCircle));
v1.emplace_back(std::move(anotherLine));
std::cout << v1[0]->get_radius() << std::endl;
std::cout << v1[1]->segment_id << std::endl;
//VERSION 2: Compiles
std::vector<std::unique_ptr<segment>> v2;
v2.emplace_back(std::make_unique<circle>(r, c));
v2.emplace_back(std::make_unique<Line>(start, end));
//=================================================================
//now I want to implement this as a function call
//=================================================================
std::vector<std::unique_ptr<segment>> v3;
//VERSION 5:
auto myLine2 = std::make_unique<Line>(start, end);
add_segment(v3, std::move(myLine2)); //shall add object of class Line or circle (derived from virtual segment class, see above) to vector v3. In this example a Line but might be a circle
}
Your function add_segment is taking the vector by value. This fails to compile because the vector is uncopyable, as unique pointers are uncopyable. Even if you used a copyable pointer type, it would be a pointless method as the copy is destroyed at the end of the function.
You will also need to move the line_or_circle parameter in the body of add_segment.
template<typename T1, typename T2>
inline void add_segment(T1 & v, T2 line_or_circle)
{
v.emplace_back(std::move(line_or_circle));
}

How to construct base class multiple times in derived constructor

Hello I I have problem on my assignment which I need to init base constructor which is point multiple time in derived constructor which is polygon.
The polygon have at least 3 point , each point have a coordinate value. any one have ideas how to init base constructor multiple time in constructor init?
The inheritance ideas is not my ideas , is the assignment question.
this is the question
Polygon  (constructor) creates a polygon with npoints vertices, the vertices take their values from those stored in the array points. Note that the array points should not be assumed to persist; it may be deleted after the constructor is invoked.
struct PointType
{
float x;
float y;
};
class Point
{
public:
Point(const PointType& center );
virtual ~Point();
private:
PointType m_center;
};
class Polygon : public Point
{
public:
Polygon(const PointType* points, int npoints);
~Polygon();
const VectorType& operator[](int index) const;
private:
int m_npoints;
Object::PointType * m_pt;
};
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include "Object.hpp"
using namespace std;
const float eps = 1e-5f;
bool Near(float x, float y)
{
return abs(x-y) < eps;
}
float frand()
{
return 10.0f*float(rand())/float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0,
max_count = 0;
// Polygon tests
int n = 3 + rand()%8;
float *xs = new float[n],
*ys = new float[n];
float x = 0, y = 0;
PointType *Ps = new PointType[n];
for (int i=0; i < n; ++i) {
xs[i] = frand(), ys[i] = frand();
Ps[i] = PointType(xs[i],ys[i]);
x += xs[i], y += ys[i];
}
}
Point::Point(const PointType& center)
: m_center{center}
{
}
// this is wrong, can correct me how to construct it?
Polygon::Polygon(const PointType* points, int npoints, float depth)
:m_npoints{npoints} , m_pt{new Object::PointType[npoints]}, Point (*m_pt ,depth)
{
for(int i=0; i < m_npoints ; ++i)
{
m_pt[i] = points[i];
}
}
enter code here
this the assignment structure like
enter image description here
I took away other object class implementation
Your assignment text doesn't say anything about inheritance. It essentially describes composition. Go from here:
class Polygon
{
public:
// constructor should allocate the array
Polygon(const PointType* points, int npoints);
~Polygon();
private:
Point *m_npoints; // or use smart pointer if you're allowed to.
};
It is a trick question, is actually want me to find centroid point of polygon.
So I need a private compute center point of polygon function and return the result of center point of polygon, and then call the function in point constructor when init.

Point, square, and cube program help on C++

I've been writing a program for CS class that's supposed to get the X and Y coordinates from the user, as well as the length of a square and the height of the cube, and it should then calculate the area of the square and the surface area and volume of the cube (plus some coordinates stuff but that's not a pressing issue right now)
I've written the test file and it compiled successfully, but I've been getting very long answers for the square and cube properties that are obviously wrong. Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?
Point.h
class Point
{
protected:
double Xint, Yint;
public:
Point();
void setX(double);
void setY(double);
double getX() const;
double getY() const;
};
Point.ccp
Point::Point()
{
Xint = 0;
Yint = 0;
}
void Point::setX(double x)
{ Xint = x; }
void Point::setY(double y)
{ Yint = y; }
double Point::getX() const
{ return Xint; }
double Point::getY() const
{ return Yint; }
Square.h
#include "Point.h"
class Square : public Point
{
protected:
Point lowerLeft;
double sideLength;
public:
Square(double sideLength, double x, double y) : Point()
{
sideLength = 0.0;
x = 0.0;
y = 0.0;
}
void setLowerLeft(double, double);
void setSideLength(double);
double getSideLength() const;
double getSquareArea() const;
};
Square.ccp
#include "Square.h"
void Square::setLowerLeft(double x, double y)
{
lowerLeft.setX(x);
lowerLeft.setY(y);
}
void Square::setSideLength(double SL)
{ sideLength = SL; }
double Square::getSideLength() const
{ return sideLength; }
// Calculate the area of square
double Square::getSquareArea() const
{ return sideLength * sideLength; }
Cube.h
#include "Square.h"
class Cube : public Square
{
protected:
double height;
double volume;
public:
Cube(double height, double volume) : Square(sideLength, Xint, Yint)
{
height = 0.0;
volume = 0.0;
}
double getSurfaceArea() const;
double getVolume() const;
};
Cube.ccp
#include "Cube.h"
// Redefine GetSquareArea to calculate the cube's surface area
double Cube::getSurfaceArea() const
{ return Square::getSquareArea() * 6; }
// Calculate the volume
double Cube::getVolume() const
{ return getSquareArea() * height; }
"Can anyone point out whatever logical errors I might have or if I have the access specification and relationship between the classes wrong?"
Well, from our well known 3-dimensional geometry a cube is made up from exactly 6 squares.
So how do you think inheriting a Cube class from a Square actually should work well?
You can easily define a Cube class by means of a fixed Point (e.g. the upper, left, front corner) and a fixed size of the edge length.
If you really want and need to, you can add a convenience function for your Cube class, that returns all of the 6 Squares it consist of in 3 dimensional space:
class Cube {
public:
Cube(const Point& upperLeftFrontCorner, double edgeLength);
std::array<Square,6> getSides() const;
};

I do not understand the output I'm getting for this program. [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Inheritance program for class polygon which is the base class and I created a derived class call rectangle. In my polygon base class I have a constructor and destructor and two print functions for area and perimeter. In my derived class I have a constructor and destructor and two print functions for area and perimeter and calc area and calc perimeter functions.
What I don't understand is the output I get when I run this program right now. The output I want is area = 45 perimeter = 28. I get this output when I use rect_1.calcarea() but want it using rect_1.printarea().
#include<iostream>
using namespace std;
class polygon
{
protected:
double area;
double perimeter;
public:
polygon(){}
virtual ~polygon(){ }
virtual double printarea() const { return area ;}
virtual double printperimeter() const { return perimeter ;}
};
class rectangle : public polygon
{
public:
rectangle(double , double ) ;
~rectangle(){ }
double calcarea() ;
double calcperimeter() ;
virtual double printarea() const { return area ;}
virtual double printperimeter() const { return perimeter ;}
private:
double length;
double width;
};
rectangle::rectangle(double l , double w)
{
length = l;
width = w;
}
double rectangle::calcarea()
{
area = length*width;
return area;
}
double rectangle::calcperimeter()
{
perimeter = length + width;
perimeter = perimeter * 2;
return perimeter;
}
void main ()
{
rectangle rect_1 (9.0, 5.0);
cout<<"The Area of Rect_1 is " <<rect_1.printarea() <<endl;
cout<<"The Perimeter of Rect_1 is " <<rect_1.printperimeter() <<endl;
system("pause");
}
printarea() is just returning the value of the member variable area. You're a) not initialising it to anything and b) not calculating the area anywhere.
I'd hazard a guess that your output is either zero or garbage—depending on compiler options—because area is not initialised (i.e. given a value).
If you call calcarea() inside the rectangle's constructor, or in main after instantiating your instance of it, then printarea() would yield the correct value. You could even call calcarea() inside printarea() to be sure the value is always up to date when needed.
Try the solution below. This will solve your problem.
Here is what I've changed:
I have made Polygon as abstract class, as you want to call only printarea or printperimeter of Polygon. Furthermore, I have called calcarea and calcperimeter, respectively. Although the same can be done in the body of printarea/printperimeter of Rectangle. There is no need to call calcarea and calcperimeter.
#include<iostream>
using namespace std;
class polygon
{
protected:
double area;
double perimeter;
public:
polygon(){}
virtual ~polygon(){ }
virtual double printarea() = 0;
virtual double printperimeter() = 0;
};
class rectangle : public polygon
{
public:
rectangle(double , double ) ;
~rectangle(){ }
double calcarea() ;
double calcperimeter() ;
double printarea() { return calcarea();}
double printperimeter() { return calcperimeter() ;}
private:
double length;
double width;
};
rectangle::rectangle(double l , double w)
{
length = l;
width = w;
}
double rectangle::calcarea()
{
area = length*width;
return area;
}
double rectangle::calcperimeter()
{
perimeter = length + width;
perimeter = perimeter * 2;
return perimeter;
}
void main ()
{
rectangle rect_1 (9.0, 5.0);
cout<<"The Area of Rect_1 is " <<rect_1.printarea() <<endl;
cout<<"The Perimeter of Rect_1 is " <<rect_1.printperimeter() <<endl;
system("pause");
}