CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18

Thread: hierarchy of shapes

  1. #1
    Join Date
    Mar 2008
    Posts
    55

    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;
    }

  2. #2
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    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.

  3. #3
    Join Date
    Mar 2008
    Posts
    55

    Re: hierarchy of shapes

    Quote 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

  4. #4
    Join Date
    Oct 2006
    Location
    Singapore
    Posts
    346

    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.
    Believe in your Dreams, Work for what you Believe in.
    My thoughts? Angelo's Stuff
    Some fun things I've done: RayWatch, QuickFeed, ACSVParser

    @ngelo

  5. #5
    Join Date
    Apr 2000
    Location
    Frederick, Maryland
    Posts
    507

    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;
    }

  6. #6
    Join Date
    Mar 2008
    Posts
    55

    Re: hierarchy of shapes

    Quote 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.

  7. #7
    Join Date
    Oct 2006
    Location
    Singapore
    Posts
    346

    Re: hierarchy of shapes

    Quote 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.
    Believe in your Dreams, Work for what you Believe in.
    My thoughts? Angelo's Stuff
    Some fun things I've done: RayWatch, QuickFeed, ACSVParser

    @ngelo

  8. #8
    Join Date
    Mar 2008
    Posts
    55

    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;
    }

  9. #9
    Join Date
    Oct 2006
    Location
    Singapore
    Posts
    346

    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?
    Believe in your Dreams, Work for what you Believe in.
    My thoughts? Angelo's Stuff
    Some fun things I've done: RayWatch, QuickFeed, ACSVParser

    @ngelo

  10. #10
    Join Date
    Mar 2008
    Posts
    55

    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;
    }

  11. #11
    Join Date
    Oct 2006
    Location
    Singapore
    Posts
    346

    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.
    Believe in your Dreams, Work for what you Believe in.
    My thoughts? Angelo's Stuff
    Some fun things I've done: RayWatch, QuickFeed, ACSVParser

    @ngelo

  12. #12
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    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.

  13. #13
    Join Date
    Oct 2006
    Location
    Singapore
    Posts
    346

    Re: hierarchy of shapes

    Quote 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.
    Quote 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.
    Believe in your Dreams, Work for what you Believe in.
    My thoughts? Angelo's Stuff
    Some fun things I've done: RayWatch, QuickFeed, ACSVParser

    @ngelo

  14. #14
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: hierarchy of shapes

    Quote 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

  15. #15
    Join Date
    Mar 2008
    Posts
    55

    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.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)