exercise.h is as below
#ifndef EXERCISE_H_
#define EXERCISE_H_
// ROOT namespace
namespace root{
// USHORT definition
typedef unsigned short ushort;
// PI DEFINITION
const double PI = 3.141592;
class shape {
double height;
double width;
public:
shape(double h = 1, double w = 1);
virtual ~shape(){}
double getHeight() const;
double getWidth() const;
virtual double area() const = 0;
};
class rectangle : virtual public shape{
public:
rectangle(double height = 1, double width = 1);
double area() const;
};
class triangle : virtual public shape {
public:
triangle(double h = 1, double w = 1);
double area() const;
};
class someShape : public rectangle, public triangle{
public:
someShape(double rh = 1, double rw = 1, double th = 2, double tw = 2);
double area() const;
double trySomething() const;
};
} // NAMESPACE
#endif /* EXERCISE_H_ */
exercise.cpp is like this
#include <iostream>
#include <cmath>
#include "exercise.h"
using std::cout;
using std::cin;
using std::endl;
using root::ushort;
// BEGIN SHAPE CLASS
root::shape::shape(double h, double w) : height(h), width(w){
}
double root::shape::getHeight() const{
return this->height;
}
double root::shape::getWidth() const{
return this->width;
}
// END SHAPE CLASS
// BEGIN RECTANGLE CLASS
root::rectangle::rectangle(double h, double w) : shape(h,w){
}
double root::rectangle::area() const{
return this->getHeight() * this->getWidth();
}
// END RECTANGLE CLASS
// BEGIN TRIANGNLE CLASS
root::triangle::triangle(double h, double w) : shape(h,w){
}
double root::triangle::area() const{
return this->getHeight() * this->getWidth() / 2;
}
// END TRIANGLE CLASS
root::someShape::someShape(double rh, double rw, double th, double tw) : rectangle(rh,rw), triangle(th,tw){
}
double root::someShape::area() const {
return rectangle::area();
}
double root::someShape::trySomething() const{
return triangle::getHeight() * rectangle::getWidth();
}
and in main
#include <iostream>
#include "exercise.h"
using std::cout;
using std::cin;
using std::endl;
int main(){
root::shape *ptrShape;
ptrShape = new root::someShape(3,2,4,3);
cout << "shape area: " << ptrShape->area() << endl;
delete ptrShape;
}
when i create an someShape object i only got the default values. although i initilize the deriving class. And there is another thing. It is the fact that we derived Rectangle and Triangle seperately and from those object we derived an other object. How will compiler decide which area() function to use?
The problem here is that you have a virtual inheritance from shape to rectangle and triangle, so the constructors of rectangle and triangle does not initialize shape. Your someShape constructor is equivalent to:
root::someShape::someShape(double rh, double rw, double th, double tw) :
rectangle(rh,rw), triangle(th,tw), shape() {
}
Which is why you get the default values 1 and 1. Also, note that since you have virtual inheritance, you cannot store different height and width for the rectangle and the triangle. Your constructor should be something like:
root::someShape::someShape(double h, double w) :
rectangle(h, w), triangle(h, w), shape(h, w) {
}
Or if you do not want to have a single instance of shape, you should remove the virtual inheritance of rectangle and triangle.
See also c++ virtual inheritance.
The problem is that you are doing virtual inheritence i.e. rectangle and triangle inherit shape using the virtual keyword. So there is a single instance of shape class that is shared among the derived classes. Hence the constructor calls from rectangle and triangle to shape are completely skipped by the compiler.
Check this for more details:
http://www.cprogramming.com/tutorial/virtual_inheritance.html
https://isocpp.org/wiki/faq/multiple-inheritance
Related
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;
}
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.
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.
I am getting a compilation error saying " ‘PointType’ is not a member of ‘Point’ " I do not know what I need to implement in my code. Been thinking for a while now. I've tried adjusting the codes here and there a few times. But could not think of a solution for this. I'm a little confused by what "Point point(Point::PointType(x, y), depth);" in the main() wants. What exactly is PointType(x,y)? Can anyone enlighten me with what I should do? Would appreciate anyone's help on this. Side Note: Main() can't be touched. Thanks!
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
struct PointType
{
float x;
float y;
PointType(const float x1, const float y1) :x(x1),y(y1){}
};
class Object
{
private:
float d;
PointType * pt;
public:
Object(float n) : d(n){}
float depth() const
{
return d;
}
};
class Point :public Object
{
private:
PointType mpoint;
public:
Point(const PointType& pt, float& y1) : mpoint(pt), Object(y1) {}
virtual ~Point();
};
Main file:
const float EPSILON = 1e-5f;
bool is_near(float x, float y)
{
return std::abs(x - y) < EPSILON;
}
float frand()
{
return 10.0f * float(rand()) / float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0;
int max_count = 0;
float x = frand();
float y = frand();
float depth = frand();
Point point(Point::PointType(x, y), depth);
if (is_near(point.depth(), depth))
{
++count;
}
else
{
std::cout << " - Point::depth test failed" << std::endl;
}
++max_count;
}
You've got a set circular declarations that can't be resolved if you can't change main(). You currently have PointType as a struct outside of the Point class. That's fine, but then you need to change the line in main() from:
Point point(Point::PointType(x, y), depth);
to:
Point point(PointType(x, y), depth);
But if you can't do that, then you can't ever compile this because Point is a subclass of Object, but Object requires a Point::PointType which can't have been defined yet. In order to have PointType be owned by Point, you need to declare it like this:
class Point :public Object
{
struct PointType
{
float x;
float y;
PointType(const float x1, const float y1) :x(x1),y(y1){}
};
private:
PointType mpoint;
public:
Point(const PointType& pt, float& y1) : mpoint(pt), Object(y1) {}
virtual ~Point();
};
But once you put PointType into Point, you can't declare any member of Object to have a type of Point::PointType because Point inherits from Object.
You could declare Object::pt to be a void* but that throws away type information which is dangerous.
I am receiving the "Debug error" CRT detected that the application wrote to memory after end of heap. But I don't understand why and can't find any similar examples.
The full code is...
Although I think it may just be a problem with main.
#include <iostream>
#include <cmath>
#include <array>
using namespace std;
// Declare global consts
const double pi = 3.1415926583;
// Base class Shape
class Shape{
protected:
double *sides;
public:
Shape(const int n){ //parameterized for n dimensional shape
sides = new double[n];
}
// need virtual destructor
virtual ~Shape(){
delete[] sides;
}
virtual double area() const = 0; // pure virtual function for area
virtual double volume() const = 0; // pure virtual function for volume
};
//////////////////////////////////////////////////////////
//Derived classes for 2D and 3D Shapes
class Shape2D : public Shape{ // inherit shape
protected:
int n = 2; //n denotes the number of dimensions
public:
// default constructor
Shape2D() :Shape(n){}
// param constructor
Shape2D(const double side1, const double side2) :Shape(n){
sides[0] = side1; sides[1] = side2;
}
virtual ~Shape2D(){} //virtual destructor
double volume() const { cout << "trying to calculate volume of 2d shape..." << endl; return 0; };
};
/////////////////////////////////////////////////////////////////////
//2D shapes
class Rectangle : public Shape2D{
public:
// constructors
Rectangle() :Shape2D() {}
Rectangle(const double side1, const double side2) :Shape2D(side1, side2){}
~Rectangle(){}
double area() const { return (sides[0] * sides[1]); }
};
int main(){
Shape **ShapePointer = new Shape*[2];
ShapePointer[0] = new Rectangle(2, 5);
ShapePointer[1] = new Rectangle(1, 3);
// clean up
delete ShapePointer[0];
delete ShapePointer[1];
delete[] ShapePointer;
system("pause");
return 0;
}
Danger!!!
protected:
int n = 2; //n denotes the number of dimensions
public:
// default constructor
Shape2D() :Shape(n){}
n is undefined when you initialize Shape(n)
Same problem with
Shape2D(const double side1, const double side2) :Shape(n)
If you can, define n as static const (or static constexpr, because you tagged C++11)
protected:
static constexpr int n = 2; //n denotes the number of dimensions
Otherwise you should define a static const/constexpr variable (say nDef), with value 2, and initialize both n and Shape() with this constant.
Anyway, take in count that, now, Shape (a base class for Shape2D) is initialized before n, that is a member of the class.
the problem is the following two lines of the code:
int n = 2; //n denotes the number of dimensions
Shape2D(const double side1, const double side2) :Shape(n){ ... }
The problem is the Shape() gets executed before the n is initialized. See constructors-called-before-initializing-variables for details.
To solution to this would be to create a the following methods in the Shape class
protected:
void InitializeBuffer(const int n)
{
sides = new double[n]
}
and instead of initialize the sides in the parent constructor, call this InitializeBuffer with in the constructor of the Shape2D class
Shape2D(const double side1, const double side2) :Shape()
{
InitializeBuffer (n);
sides[0] = side1; sides[1] = side2;
}
I need to be able to use a base pointer to hold the address of either a
rectangle or a circle. Which one would be determined at run time. I then want to
use the pointers to call different virtual functions depending on which type
they are. I can get this concept to work if the functions only use one Shape
pointer. However many of my functions require two objects to work.
If I use a pure virtual functions, both Rectangle and Circle classes become
abstract and I can not use the objects (error C2259). If I declare the functions
as I did down below, all of the calls go to the Base class Shape. Any help is
greatly appreciated.
class Shape {
public:
virtual double overlappingArea(const Shape&)const {return 0;};
//replacing with a pure virtual function causes the other classes to become abstract
//virtual double overlappingArea(const Shape&)const = 0;
//This returns error C2259 (or pure virtual function has no overload)
//I know this is because the program has no overloads with identical parameters
};
class Rectangle : virtual public Shape {
public:
Rectangle(int X, int Y, int L, int W) : x(X), y(Y), l(L), w(W) {}
double overlappingArea(const Rectangle& R)const {
double area = 1.1;
//code that finds the overlapping area
return area;
}
double overlappingArea(const Circle& C)const {
double area = 1.2;
//code that finds the overlapping area
return area;
}
private:
int x, y, l, w;
};
class Circle: virtual public Shape {
public:
Circle(int X, int Y, int R) : x(X), y(Y), r(R) {}
double overlappingArea(const Rectangle& R)const {
double area = 2.1;
//code that finds the overlapping area
return area;
}
double overlappingArea(const Circle& C)const {
double area = 2.2;
//code that finds the overlapping area
return area;
}
private:
int x, y, r;
};
int main() {
Shape* F1 = new Rectangle(0,0,1,1);
Shape* F2 = new Rectangle(1,1,2,2);
Shape* C1 = new Circle(0,0,1);
Shape* C2 = new Circle(1,1,2);
double areaFF, areaFC, areaCC;
areaFF = F1->overlappingArea(*F2);
areaFC = F1->overlappingArea(*C1);
areaCC = C1->overlappingArea(*C2);
return 0;
}
All the areas end up equaling 0.
I want areaFF = 1.1 , areaFC = 1.2 , areaCC = 2.2
Thanks for the help
Working code if you're interested
#include <iostream>
using namespace std;
class Rectangle;
class Circle;
class Shape {
public:
virtual double overlapwith(const Shape&)const = 0;
virtual double overlap(const Rectangle&)const = 0;
virtual double overlap(const Circle&)const = 0;
};
class Circle : public Shape {
public:
Circle() : x(0), y(0), r(0) {
}
Circle(int X, int Y, int R) : x(X), y(Y), r(R) {
}
double overlapwith(const Shape &with)const {
cout << "\nCirc::overlapwith(const Shap&)const";
return with.overlap(*this);
}
double overlap(const Rectangle &w)const {
cout << "\nCirc::overlap(const Rect&)const";
return 12;
}
double overlap(const Circle &w)const {
cout << "\nCirc::overlap(const Circ&)const";
return 11;
}
private:
int x, y, r;
};
class Rectangle : public Shape {
public:
Rectangle() : x(0), y(0), l(0), w(0) {
}
Rectangle(int X, int Y, int L, int W) : x(X), y(Y), l(L), w(W) {
}
double overlapwith(const Shape &with)const {
cout << "\nRect::overlapwith(const Shap&)const";
return with.overlap(*this);
}
double overlap(const Rectangle &w)const {
cout << "\nRect::overlap(const Rect&)const";
return 22;
}
double overlap(const Circle &w)const {
cout << "\nRect::overlap(const Circ&)const";
return 21;
}
private:
int x, y, l, w;
};
int main() {
Shape* F1 = new Rectangle(0,0,1,1);
Shape* F2 = new Rectangle(1,1,2,2);
Shape* C1 = new Circle(0,0,1);
Shape* C2 = new Circle(1,1,2);
double ff, fc, cf, cc;
ff = F1->overlapwith(*F2);
fc = F1->overlapwith(*C2);
cf = C1->overlapwith(*F2);
cc = C1->overlapwith(*C2);
cout << "\n\n\tff : " << ff
<< "\n\tfc : " << fc
<< "\n\tcf : " << cf
<< "\n\tcc : " << cc;
int pb; cin >> pb;
return 0;
}
Define two more pure virtual methods in the base class, in addition to the existing virtual methods, which can be pure. You will need to do some simple forward declarations:
class Rectangle;
class Circle;
class Shape {
public:
virtual double overlappingArea(const Shape&) const=0;
virtual double overlappingAreaWith(const Rectangle&) const=0;
virtual double overlappingAreaWith(const Circle&) const=0;
};
In each subclass, implement the first virtual method (the existing one) by invoking overlappingAreaWith() for the passed Shape & parameter, passing *this as the parameter:
class Rectangle {
// ...
double overlappingArea(const Shape &with) const override
{
return with.overlappingAreaWith(*this);
}
};
class Circle {
// ...
double overlappingArea(const Shape &with) const override
{
return with.overlappingAreaWith(*this);
}
};
Now, implement the other two overlappingAreaWith() methods in both Circle and Rectangle subclasses. They will now receive the other object, as either a Circle or a Rectangle parameter, as the case may be.
Each subclass is correctly implementing all three pure virtual methods.
I am learning C++ and I have a question.
I made a class in Netbeans, which made Rectangle.h and Rectangle.cpp. I am trying to add methods that output the Area and Perimeter of the rectangle's l and w variables. I don't know how to create methods in a class and how to incorporate them in the Rectangle.h file.
Here's what I'm trying to do:
Rectangle rct;
rct.l = 7;
rct.w = 4;
cout << "Area is " << rct.Area() << endl;
cout << "Perim is " << rct.Perim() << endl;
Can someone explain how to do this? I'm so confused.
Thanks,
Lucas
In the .h file you have the class definition, where you write down the member variables en member functions (generally as prototype)
In the .cpp file you declare the methods body. Example:
rectangle.h:
class rectangle
{
public:
// Variables (btw public member variables are not a good
// practice, you should set them as private and access them
// via accessor methods, that is what encapsulation is)
double l;
double w;
// constructor
rectangle();
// Methods
double area();
double perim();
};
rectangle.cpp:
#include "rectangle.h" // You include the class description
// Contructor
rectangle::rectangle()
{
this->l = 0;
this->w = 0;
}
// Methods
double rectangle::area()
{
return this->w * this->l;
}
double rectangle::perim()
{
return 2*this->w + 2*this->l;
}
But like gmannickg said you should read a book about c++ or a real tutorial, that will explain you how the syntax works. And Object Oriented Programming (if you are not familiar with it)
Quite easy - this is just an example and one possible implementation. Note that the following adds some additional stuff (like const and a constructor) you don't necessarily need; depending on your useage.
class Rectangle {
private:
double l, w;
// This constructor has optional arguments, meaning you can skip them (which will result in them being set to 0).
public:
Rectangle(const double l = 0, const double w = 0);
double Area(void) const; // the const keyword after the parameter list tells the compiler that this method won't modify the actual object
double Perim(void) const;
}
Rectangle::Rectangle(const double _l, const double _w) : l(_l), w(_w) { // this is an initializer list - as an alternative, here it would be possible to just assign the values inside the function body
}
double Rectangle::Area(void) const {
return l * w;
}
double Rectangle::Perim(void) const {
return l + l + w + w;
}
The header (.h) file is mainly concerned with specifying the interface. While you can implement functions there as well, you typically do not. Instead, you define the class in the header, and then implement it in the .cpp (.hpp, whatever) file. For example, your rectangle class:
// Rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
class Rectangle {
public:
// constructors, just initialize our private members
Rectangle(int x, int y, int w, int h)
: _x(x), _y(y), _w(w), _h(h) { }
Rectangle() : _x(0), _y(0), _w(0), _h(0) { }
// implement these in Rectangle.cpp
int get_x();
void set_x(int x);
int get_y();
void set_y(int y);
int get_width();
void set_width(int w);
int get_height();
void set_height(int h);
int Area();
int Perim();
private:
int _x, _y, _w, _h;
};
#endif
// Rectangle.cpp
#include "Rectangle.h"
#include <algorithm>
using std::max;
int Rectangle::get_x() {
return _x;
}
void Rectangle::set_x(int x) {
_x = x;
}
int Rectangle::get_y() {
return _y;
}
void Rectangle::set_y(int y) {
_y = y;
}
int Rectangle::get_width() {
return _w;
}
void Rectangle::set_width(int w) {
_w = max(w, 0);
}
int Rectangle::get_height() {
return _h;
}
void Rectangle::set_height(int h) {
_h = max(h, 0);
}
int Rectangle::Area() {
return _w * _h;
}
int Rectangle::Perim() {
return _w * 2 + _h * 2;
}