-
May 12th, 2008, 03:57 PM
#1
hierarchy of shapes
okay im working on a shapes hierarchy and i want to know if u can find whats my problem in my program. im thinking it might be my virtual void function or its in the main. this is what i have to do ,create a program that uses vector of shapes pointers to objects of each concrete class in the hierarchy, the program should print the object to which each vector element points. this is what i have so far:
Code:
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
class Shape {
public:
Shape( double = 0.0, double = 0.0 ); // default constructor
double getCenterX() const; // return x from coordinate pair
double getCenterY() const; // return y from coordinate pair
virtual void print() const = 0; // output Shape object
protected:
double xCenter; // x part of coordinate pair
double yCenter; // y part of coordinate pair
}; // end class Shape
class TwoDimensionalShape : public Shape {
public:
// default constructor
TwoDimensionalShape( double x, double y ) : Shape( x, y ) { }
virtual double getArea() const = 0; // area of TwoDimensionalShape
}; // end class TwoDimensionalShape
class Square : public TwoDimensionalShape{
public:
Square(int Length): TwoDimensionalShape(Length,Length){}
virtual ~Square(){}
virtual double getArea()const=0;
protected:
int Length;
};
class Circle : public TwoDimensionalShape{
public:
Circle(int radius): TwoDimensionalShape(radius,radius){}
virtual ~Circle(){}
virtual double getArea()const=0;
protected:
int radius;
};
class Triangle : public TwoDimensionalShape{
public:
Triangle(int base,int height): TwoDimensionalShape(base,height){}
virtual ~Triangle(){}
virtual double getArea()const=0;
protected:
int base;
int height;
};
int main(){
vector <Shape*> shapes(3);
shapes[0]= new Square(4);
shapes[1]= new Circle(3);
shapes[2]= new Triangle(2,4);
return 0;
}
double Square::getArea() const
{
return Length*Length;
}
double Circle::getArea() const
{
return 3.14 * radius*radius;
}
double Triangle::getArea() const
{
return (base * height)/2;
}
void Shape::print() const {
cout << "Area is: " << pCircle->getArea() << endl;
cout << "Area is: " << pSquare->getArea() << endl;
cout << "Area is: " << pTriangle->getArea() << endl;
}
-
May 12th, 2008, 04:05 PM
#2
Re: hierarchy of shapes
You have not told us anything about what's actually going wrong.
However, offhand I notice that TwoDimensionalShape lacks a virtual destructor.
-
May 12th, 2008, 04:21 PM
#3
Re: hierarchy of shapes
Originally Posted by Lindley
You have not told us anything about what's actually going wrong.
However, offhand I notice that TwoDimensionalShape lacks a virtual destructor.
well i get 9 errors i think some come from the same problem
error C2259: 'Square' : cannot instantiate abstract class
due to following members:
'void Shape::print(void) const' : is abstract
cpp(11) : see declaration of 'Shape::print'
'double Square::getArea(void) const' : is abstract
cpp(29) : see declaration of 'Square::getArea'
error C2259: 'Circle' : cannot instantiate abstract class
due to following members:
'void Shape::print(void) const' : is abstract
see declaration of 'Shape::print'
'double Triangle::getArea(void) const' : is abstract
cpp(47) : see declaration of 'Triangle::getArea'
error C2065: 'pCircle' : undeclared identifier
error C2227: left of '->getArea' must point to class/struct/union/generic type
type is ''unknown-type''
error C2065: 'pSquare' : undeclared identifier
error C2227: left of '->getArea' must point to class/struct/union/generic type
type is ''unknown-type''
c:error C2065: 'pTriangle' : undeclared identifier
error C2227: left of '->getArea' must point to class/struct/union/generic type
-
May 12th, 2008, 04:34 PM
#4
Re: hierarchy of shapes
As long as a class has unimplemented pure virtual functions, that class cannot be instantiated.
Square derives from TwoDimensionalShape which in turn derives from Shape. Now, Shape has a pure virtual function named print(). I see that you have written a definition for this function but it won't matter because the function has been declared as pure virtual in its class. TwoDimensionalShape does not provide an implementation for this function. It therefore, falls to Square to provide an implementation for this function. Also, Square itself has a pure virtual function named getArea(). The same goes for the classes Circle and Triangle.
The other error stems from the fact that you use three pointers pCircle, pSquare and pTriangle without ever declaring them in Shape::print().
I think you may need to take this program back to the drawing board.
Last edited by angelorohit; May 12th, 2008 at 04:40 PM.
-
May 12th, 2008, 04:42 PM
#5
Re: hierarchy of shapes
Your program has severl problems.
1. Where did you define pCircle, pSquare and pTriangle?
2. Your Cirlce, Square and Triangle class has pure virtual function (getArea) therefore these are abstract classes, you can not create object of abstract class as you are doing like this
Code:
shapes[0]= new Square(4);
shapes[1]= new Circle(3);
shapes[2]= new Triangle(2,4);
3. Your code has memory leak (if you solve the compilation errors and make it run). You allocate the memory using new, but never delete it.
4. You getArea() function is constant in TwoDimensionalShape class, but non-constant in derived classes. Therefore it is still not implemented and derived class will still be abstract classes.
5. The constructor of Shape class does not have a body.
If i understand what you wanted to do, then here is the minimum changes i can do in your program to make it work.
Code:
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
class Shape {
public:
Shape( double = 0.0, double = 0.0 ) { }; // default constructor
double getCenterX() const; // return x from coordinate pair
double getCenterY() const; // return y from coordinate pair
virtual void print() const = 0; // output Shape object
protected:
double xCenter; // x part of coordinate pair
double yCenter; // y part of coordinate pair
}; // end class Shape
class TwoDimensionalShape : public Shape {
public:
// default constructor
TwoDimensionalShape( double x, double y ) : Shape( x, y ) { }
virtual double getArea() const = 0; // area of TwoDimensionalShape
}; // end class TwoDimensionalShape
class Square : public TwoDimensionalShape{
public:
Square(int Length): TwoDimensionalShape(Length,Length){}
virtual ~Square(){}
virtual double getArea() const;
void print() const;
protected:
int Length;
};
class Circle : public TwoDimensionalShape{
public:
Circle(int radius): TwoDimensionalShape(radius,radius){}
virtual ~Circle(){}
virtual double getArea() const;
void print() const;
protected:
int radius;
};
class Triangle : public TwoDimensionalShape{
public:
Triangle(int base,int height): TwoDimensionalShape(base,height){}
virtual ~Triangle(){}
virtual double getArea() const;
void print() const;
protected:
int base;
int height;
};
int main(){
vector <Shape*> shapes(3);
shapes[0]= new Square(4);
shapes[1]= new Circle(3);
shapes[2]= new Triangle(2,4);
for (int iIndex = 0; iIndex < 3; ++iIndex)
{
shapes[iIndex]->print();
}
for (int iIndex = 0; iIndex < 3; ++iIndex)
{
delete shapes[iIndex];
}
return 0;
}
double Square::getArea() const
{
return Length*Length;
}
double Circle::getArea() const
{
return 3.14 * radius*radius;
}
double Triangle::getArea() const
{
return (base * height)/2;
}
void Square::print() const {
cout << "Area is: " << getArea() << endl;
}
void Circle::print() const {
cout << "Area is: " << getArea() << endl;
}
void Triangle::print() const {
cout << "Area is: " << getArea() << endl;
}
-
May 12th, 2008, 04:56 PM
#6
Re: hierarchy of shapes
Originally Posted by Zeeshan
If i understand what you wanted to do, then here is the minimum changes i can do in your program to make it work.
[/CODE]
yes that is what i wanted to accomplish with my program thanks. but when i compile your program it gives me unrealistic numbers like negatives. is it because in the print function the getArea() doesnt know which getArea to use.
Last edited by ptg; May 12th, 2008 at 05:10 PM.
-
May 12th, 2008, 05:10 PM
#7
Re: hierarchy of shapes
Originally Posted by ptg
yes that is what i wanted to accomplish with my program thanks. but when i compile your program it gives me unrealistic numbers. like negatives
It's because your constructors are all wrong. You should write individual constructors for Square, Circle and Triangle and copy arguments passed for these constructors to the member variables of each corresponding class. Also, remove the constructors in Shape and TwoDimensionalShape and let the compiler generate default ones.
-
May 12th, 2008, 05:23 PM
#8
Re: hierarchy of shapes
okay i changed my program around, since the other one was causing alot problems my new program seems to work alot better.
Code:
#include<iostream>
#include<vector>
using namespace std;
class Shape{
public:
virtual double GetArea() = 0; // pure virtual method
};
class Rect : public Shape{
public:
Rect(double initHeight, double initWidth){
Height = initHeight;
Width = initWidth;
}
virtual ~Rect(){} // virtual destructor
virtual double GetArea() { return Height * Width;}
virtual double GetPerim() { return (2 * Height) + (2 * Width);}
virtual double GetHeight() { return Height;}
private:
double Height, Width;
};
class Square : public Rect{
public:
Square(int length):Rect(length, length) {}
~Square() {}
double GetPerim() { return 4 * GetHeight();}
};
class Circle:public Shape{
public:
Circle(double radius){
r=radius;
}
virtual double GetArea() { return 3.14 * r*r;}
virtual double GetPerim() { return 2 * 3.14*r;}
private:
double r;
};
int main(){
vector <Shape*> shapes(6);
shapes[0]= new Rect(5,4);
shapes[1]= new Square(3);
shapes[2]= new Circle(2);
shapes[3]= new Rect(3,5);
shapes[4]= new Square(4);
shapes[5]= new Circle(3);
for(size_t i=0;i<shapes.size();i++){
cout<<"\nArea: "<<shapes[i]->GetArea()<<endl;
}
cout<<endl;
return 0;
}
-
May 12th, 2008, 06:17 PM
#9
Re: hierarchy of shapes
Nice to see that you followed my advice and rewrote the program from scratch. Sometimes, a good programmer must be prepared to accept that his/her program design is intrinsically faulty. A few points of advice:
1. When you want to initialize class member variables via the constructor, you can use the initialization syntax like so.
Code:
Rect(const double initHeight, const double initWidth) : height(initHeight), width(initWidth)
{}
This is supposed to be more optimized as well as more elegant.
2. Once again, you have forgotten to deallocate the memory that you reserved using new. This is something that most novice programmers forget to do. My simple philosophy is that: If you use new, then be prepared to use delete - somewhere or the other. In main itself...
Code:
for(std::vector<Shape*>::size_type i = 0; i < shapes.size(); ++i)
{
delete shapes[i];
}
3. Make the destructor of Shape virtual. The reason for doing so can be found here.
4. What?! No Triangles?
-
May 12th, 2008, 06:25 PM
#10
Re: hierarchy of shapes
okay i upgraded my program to add threedimensional and im trying to get the volume but only for the threedimensional objects. i get this error
error C2039: 'GetVolume' : is not a member of 'Shape'
but when put it in Shape it gives me errors for my twodimensional shapes.
do i have to make another vector for the volume or what could i do?
Code:
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
class Shape{
public:
virtual double GetArea() = 0;
};
class TwoDimensionalShape : public Shape {
public:
virtual double GetArea() = 0;
};
class Square : public TwoDimensionalShape{
public:
Square(double ilenght){
lenght = ilenght;
}
virtual ~Square(){}
virtual double GetArea() { return lenght * lenght;}
private:
double lenght;
};
class Circle:public TwoDimensionalShape{
public:
Circle(double radius){
r=radius;
}
virtual double GetArea() { return 3.14 * r*r;}
private:
double r;
};
class Triangle : public TwoDimensionalShape{
public:
Triangle(double ibase, double iheight){
base = ibase;
height = iheight;
}
virtual ~Triangle(){} // virtual destructor
virtual double GetArea() { return (base * height)/2;}
private:
double base,height;
};
class ThreeDimensionalShape : public Shape{
public:
virtual double GetArea() = 0;
virtual double GetVolume() = 0;
};
class Cube : public ThreeDimensionalShape{
public:
Cube(double isideLength){
sideLength = isideLength;
}
virtual ~Cube(){}
virtual double GetArea(){return 6*sideLength *sideLength;}
virtual double GetVolume(){return sideLength*sideLength *sideLength;}
private:
double sideLength;
};
class Sphere : public ThreeDimensionalShape{
public:
Sphere(double iradius){
radius = iradius;
}
virtual ~Sphere(){}
virtual double GetArea(){return 4 * 3.14 * radius * radius;}
virtual double GetVolume(){return (4/3)*3.14*radius*radius *radius;}
private:
double radius;
};
class Tetrahedron : public ThreeDimensionalShape{
public:
Tetrahedron(double iside){
side = iside;
}
virtual ~Tetrahedron(){}
virtual double GetArea(){return (side * side) * sqrt(3.0);}
virtual double GetVolume(){return (1/12)*(side *side*side)*sqrt(2.0);}
private:
double side;
};
int main(){
vector <Shape*> shapes(6);
shapes[0]= new Square(3);
shapes[1]= new Circle(2);
shapes[2]= new Triangle(2,4);
shapes[3]= new Cube(4);
shapes[4]= new Sphere(3);
shapes[5]= new Tetrahedron(2);
for(size_t i=0;i<shapes.size();i++){
cout<<"\nArea: "<<shapes[i]->GetArea()<<endl;
cout<<"\nVolume: "<<shapes[i]->GetVolume()<<endl;
}
for(size_t i=0; i < shapes.size(); i++)
{
delete shapes[i];
}
cout<<endl;
return 0;
}
-
May 12th, 2008, 07:05 PM
#11
Re: hierarchy of shapes
Consider this:
You are saying that all 3D shapes have a volume while 2D shapes do not. This premise is correct. If you were to put GetVolume() in Shape, then you would be saying "All Shapes have a volume." That is not correct. In main, you are trying to create all kinds of Shapes. However, if you try to invoke GetVolume() through a pointer of type Shape, then you are going under the assumption that all Shapes have a volume. This assumption is completely false because some of your Shapes are 2D (Circle, Square etc.), for which there are no volumes.
The trick is to check whether the Shape in question is of type ThreeDimensional or not. This can be done using a dynamic cast. Your for loop should be as follows...
Code:
for(size_t i=0;i<shapes.size();i++)
{
cout<<"\nArea: "<<shapes[i]->GetArea()<<endl;
if( ThreeDimensionalShape* p3DShape = (dynamic_cast<ThreeDimensionalShape*>(shapes[i])) )
{
std::cout<<"\nVolume: "<<p3DShape->GetVolume()<<endl;
}
}
Basically, what this does is, do a safe typecast at runtime from type Shape to type ThreeDimensional. If the cast succeeds (ie; the Shape was actually 3D) then you can display its volume happily. If the cast fails (ie; the Shape was of type TwoDimensional), then p3DShape will be a null pointer and our if condition will not be true.
Last edited by angelorohit; May 12th, 2008 at 07:08 PM.
-
May 13th, 2008, 04:44 AM
#12
Re: hierarchy of shapes
If you were to put GetVolume() in Shape, then you would be saying "All Shapes have a volume." That is not correct.
Unless you decide that a volume of zero is a valid answer for a 2D shape, which means you could create a default virtual GetVolume() in the base class which returns zero. It all depends on whether you think this makes logical sense in the context of your application.
-
May 13th, 2008, 05:29 AM
#13
Re: hierarchy of shapes
Originally Posted by JohnW@Wessex
Unless you decide that a volume of zero is a valid answer for a 2D shape, which means you could create a default virtual GetVolume() in the base class which returns zero. It all depends on whether you think this makes logical sense in the context of your application.
Yes, of course. From that point of view, all Shapes can have a volume. I deduced what the OP wanted from this statement in his/her last post.
Originally Posted by ptg
okay i upgraded my program to add threedimensional and im trying to get the volume but only for the threedimensional objects.
-
May 13th, 2008, 06:07 AM
#14
Re: hierarchy of shapes
Originally Posted by angelorohit
Yes, of course. From that point of view, all Shapes can have a volume. I deduced what the OP wanted from this statement in his/her last post.
Yes, my mistake, I missed that
-
May 13th, 2008, 01:05 PM
#15
Re: hierarchy of shapes
can any one tell me if i did the volume for the tetrahedron right because i get a volume of zero.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|